def _create_joint(fwdbwd, func, wrt, input_derivative):
  """Create a user-friendly gradient function.

  By default, gradient functions expect the stack to be passed to them
  explicitly. This function modifies the function so that the stack doesn't
  need to be passed and gets initialized in the function body instead.

  For consistency, gradient functions always return a tuple, even if the
  gradient of only one input was required. We unpack the tuple if it is of
  length one.

  Args:
    fwdbwd: An AST. The function definition of the joint primal and adjoint.
    func: A function handle. The original function that was differentiated.
    wrt: A tuple of integers. The arguments with respect to which we differentiated.

  Returns:
    The function definition of the new function.
  """
  # Correct return to be a non-tuple if there's only one element
  retval = fwdbwd.body[-1]
  if len(retval.value.elts) == 1:
    retval.value = retval.value.elts[0]

  # Make a stack init statement
  init_stack = quoting.quote('%s = tangent.Stack()' % fwdbwd.args.args[0].id)
  init_stack = comments.add_comment(init_stack, 'Initialize the tape')

  # Prepend the stack init to the top of the function
  fwdbwd.body = [init_stack] + fwdbwd.body

  # Replace the function arguments with the original ones
  grad_name = fwdbwd.args.args[1].id
  fwdbwd.args = quoting.parse_function(func).body[0].args

  # Give the function a nice name
  fwdbwd.name = naming.joint_name(func, wrt)

  # Allow the initial gradient to be passed as a keyword argument
  fwdbwd = ast_.append_args(fwdbwd, [grad_name])
  if input_derivative == INPUT_DERIVATIVE.DefaultOne:
    fwdbwd.args.defaults.append(quoting.quote('1.0'))
  return fwdbwd
Create a user-friendly gradient function.

  By default, gradient functions expect the stack to be passed to them
  explicitly. This function modifies the function so that the stack doesn't
  need to be passed and gets initialized in the function body instead.

  For consistency, gradient functions always return a tuple, even if the
  gradient of only one input was required. We unpack the tuple if it is of
  length one.

  Args:
    fwdbwd: An AST. The function definition of the joint primal and adjoint.
    func: A function handle. The original function that was differentiated.
    wrt: A tuple of integers. The arguments with respect to which we differentiated.

  Returns:
    The function definition of the new function.