def nested_map(f, obj):
  """Maps `f` recursively inside any dicts/lists/tuples in `obj`.

  Args:
    f: A function taking a single object as input. f's input must NOT be a
        dict, list, or tuple, or any subclass of those.
    obj: Either an input object to f or some nested structure of collections
        of (collections of ...) input objects to f.

  Returns:
    An object with the same nested structure as `obj`, but with each input
    object `x` replaced by `f(x)`.
  """
  if isinstance(obj, list):
    return [nested_map(f, y) for y in obj]
  if isinstance(obj, tuple):
    return tuple([nested_map(f, y) for y in obj])
  if isinstance(obj, dict):
    return {k: nested_map(f, v) for (k, v) in obj.items()}
  return f(obj)