Register a gradient function to a random string.

  In order to use a custom gradient in TensorFlow, it must be registered to a
  string. This is both a hassle, and -- because only one function can every be
  registered to a string -- annoying to iterate on in an interactive
  environemnt.

  This function registers a function to a unique random string of the form:

    {FUNCTION_NAME}_{RANDOM_SALT}

  And then returns the random string. This is a helper in creating more
  convenient gradient overrides.

  Args:
    grad_f: gradient function to register. Should map (op, grad) -> grad(s)

  Returns:
    String that gradient function was registered to.

def register_to_random_name(grad_f):
  """Register a gradient function to a random string.

  In order to use a custom gradient in TensorFlow, it must be registered to a
  string. This is both a hassle, and -- because only one function can every be
  registered to a string -- annoying to iterate on in an interactive
  environemnt.

  This function registers a function to a unique random string of the form:

    {FUNCTION_NAME}_{RANDOM_SALT}

  And then returns the random string. This is a helper in creating more
  convenient gradient overrides.

  Args:
    grad_f: gradient function to register. Should map (op, grad) -> grad(s)

  Returns:
    String that gradient function was registered to.
  """
  grad_f_name = grad_f.__name__ + "_" + str(uuid.uuid4())
  tf.RegisterGradient(grad_f_name)(grad_f)
  return grad_f_name