code: def autodiff_tree(func, wrt, motion, mode, preserve_result, check_dims,
                    verbose):
    
    # Imported here to avoid circular imports
    import tangent
    namespace = {'tangent': tangent, 'numpy': numpy}
  
    done = set()
    final = gast.Module(body=[])
    namespace.update(six.get_function_globals(func))
  
    node, required = autodiff_ast(func, wrt, motion, mode, preserve_result,
                                  check_dims, verbose)
    final.body.extend(node.body)
  
    to_do = set(required)
    if motion == 'split' and mode == 'reverse':
      done.add((func, wrt))
      to_do -= done
  
    while to_do:
      func, wrt = to_do.pop()
      namespace.update(six.get_function_globals(func))
  
      node, required = autodiff_ast(
          func=func,
          wrt=wrt,
          motion='split',
          mode=mode,
          preserve_result=True,
          check_dims=False,
          verbose=verbose)
  
      final.body.extend(node.body)
      done.add((func, wrt))
      to_do.update(required)
      to_do -= done
  
    return final, namespace
docs: Perform AD on all functions in a call tree.
  
    This function walks the call tree and differentiates each function in it. It
    also ensures that the global namespaces that each function in the call tree
    was in are merged.
  
    The `tangent` and `numpy` packages are added to the namespace here, so that
    the gradient templates can assume that they are present.
  
    Args:
      See `grad`.
  
    Returns:
      final: A single module which contains the primals and adjoints of all the
          functions in the call tree.
      namespace: A merged dictionary with all the variables in the global
          namespaces of each function. The primals and adjoints need access to
          these in order to execute.