code: def create_grad(node, namer, tangent=False):
    
    if not isinstance(node, (gast.Subscript, gast.Name, gast.Str)):
      raise TypeError
  
    if anno.hasanno(node, 'temp_var'):
      return create_grad(anno.getanno(node, 'temp_var'), namer, tangent)
  
    def _name_grad(node):
      if not isinstance(node, gast.Name):
        raise TypeError
      varname = node.id
      name = namer.grad(varname, tangent)
      grad_node = gast.Name(
          id=name, ctx=None, annotation=None)
      anno.setanno(grad_node, 'adjoint_var', node)
      return grad_node
    if isinstance(node, gast.Subscript):
      grad_node = create_grad(node.value, namer, tangent=tangent)
      grad_node.ctx = gast.Load()
      return gast.Subscript(value=grad_node, slice=node.slice, ctx=None)
    elif isinstance(node, gast.Str):
      grad_node = create_grad(
          gast.Name(id=node.s, ctx=None, annotation=None), namer, tangent=tangent)
      return gast.Str(grad_node.id)
    else:
      return _name_grad(node)
docs: Given a variable, create a variable for the gradient.
  
    Args:
      node: A node to create a gradient for, can be a normal variable (`x`) or a
          subscript (`x[i]`).
      namer: The namer object which will determine the name to use for the
          gradient.
      tangent: Whether a tangent (instead of adjoint) is created.
  
    Returns:
      node: A node representing the gradient with the correct name e.g. the
          gradient of `x[i]` is `dx[i]`.
  
          Note that this returns an invalid node, with the `ctx` attribute
          missing. It is assumed that this attribute is filled in later.
  
          Node has an `adjoint_var` annotation referring to the node it is an
          adjoint of.