def deep_apply(x, f):
    """Performs a deep application of method f() on all objects in 'x'

    Recursively enters any list/tuple/dict.
    Non-destructive, returns a new object with the same structure
    """
    if isinstance(x, (list, tuple)):
        return type(x)([deep_apply(item, f) for item in x])
    elif isinstance(x, dict):
        return {key: deep_apply(val, f) for key, val in x.items()}
    elif x is None:
        return None
    else:
        return f(x)