parameters: (func, input_types, func_name=None, grad_func=None,
                      python_grad_func=None)
return_statement: return func_def
docstring: Creates a `FunctionDef` for a python function.
  
    `func` is a Python function that receives zero or more tensors and returns at
    least one tensor.  It should add ops to the default graph the usual way by
    calling TensorFlow functions such as `tf.constant()`, `tf.matmul()`, etc.
  
    `input_types` is a dictionary of strings to `tf.Dtype` objects.  Keys are
    names arguments to `func`.  The value indicate the type of tensor expected
    by the function.
  
    The returned `FunctionDef` protocol buffer is also added to the
    default graph library.  After it has been added you can add calls to
    the function by passing it to `tf.call_function()`, together with a
    list of tensors to use as inputs for the function.
  
    Notes:
  
    *  `func` is called once, with `placeholder` tensors of the types specified in
       `input_types` as arguments.
    *  Values returned by `func` must be tensors and they are recorded as being
       the output of the function def.
    *  While `func` is a called, an empty graph is temporarily pushed as the
       default graph.  All ops added by `func` to that graph are part of the body
       of the returned function def.
  
    Example, but also see the [How To on functions](link_needed).
  
    ```python
    # A function that receives two tensors x, y and returns their
    # sum and difference.
    def my_func(x, y):
      return x + y, x - y
  
    # Create a FunctionDef for 'my_func'. (This does not change the default
    graph.)
    my_func_def = tf.define_function(my_func, {'x': tf.float32, 'y': tf.float32})
    # Alternatively:
    # my_func_def = tf.define_function(my_func, [tf.float32, tf.float32])
  
    # Build the graph, calling the function.
    a = tf.constant([1.0])
    b = tf.constant([2.0])
    c, d = tf.call_function(my_func_def, a, b, name='mycall')
    ```
  
    Args:
      func: a Python function.
      input_types: if a dict, keys are the names of the arguments of
        `func`, values are their expected `tf.DType`. Otherwise,
        a list of `tf.DType`s.
      func_name: Pyton string.  If not None, specifies the name to use when
        creating the Function.  By default, introspection on `func` is used to
        generate a name.
      grad_func: If not None, specifies the gradient function. The
                 gradient function must satisify the criterion defined in
                 function.proto:GradientDef.
      python_grad_func: If not None, specifies the gradient function with the same
                 interface as that expected by `tf.RegisterGradient`. This
                 will be called by tf.gradients to add the gradient ops to the
                 graph. No more than one of {grad_func, python_grad_func} may be
                 specified.
  
    Returns:
      A FunctionDef protocol buffer.
  
    Raises:
      ValueError: if the arguments are invalid.
docstring_summary: Creates a `FunctionDef` for a python function.
docstring_tokens: Creates a FunctionDef for a python function .
function: def define_function(func, input_types, func_name=None, grad_func=None,
                      python_grad_func=None):
    """Creates a `FunctionDef` for a python function.
  
    `func` is a Python function that receives zero or more tensors and returns at
    least one tensor.  It should add ops to the default graph the usual way by
    calling TensorFlow functions such as `tf.constant()`, `tf.matmul()`, etc.
  
    `input_types` is a dictionary of strings to `tf.Dtype` objects.  Keys are
    names arguments to `func`.  The value indicate the type of tensor expected
    by the function.
  
    The returned `FunctionDef` protocol buffer is also added to the
    default graph library.  After it has been added you can add calls to
    the function by passing it to `tf.call_function()`, together with a
    list of tensors to use as inputs for the function.
  
    Notes:
  
    *  `func` is called once, with `placeholder` tensors of the types specified in
       `input_types` as arguments.
    *  Values returned by `func` must be tensors and they are recorded as being
       the output of the function def.
    *  While `func` is a called, an empty graph is temporarily pushed as the
       default graph.  All ops added by `func` to that graph are part of the body
       of the returned function def.
  
    Example, but also see the [How To on functions](link_needed).
  
    ```python
    # A function that receives two tensors x, y and returns their
    # sum and difference.
    def my_func(x, y):
      return x + y, x - y
  
    # Create a FunctionDef for 'my_func'. (This does not change the default
    graph.)
    my_func_def = tf.define_function(my_func, {'x': tf.float32, 'y': tf.float32})
    # Alternatively:
    # my_func_def = tf.define_function(my_func, [tf.float32, tf.float32])
  
    # Build the graph, calling the function.
    a = tf.constant([1.0])
    b = tf.constant([2.0])
    c, d = tf.call_function(my_func_def, a, b, name='mycall')
    ```
  
    Args:
      func: a Python function.
      input_types: if a dict, keys are the names of the arguments of
        `func`, values are their expected `tf.DType`. Otherwise,
        a list of `tf.DType`s.
      func_name: Pyton string.  If not None, specifies the name to use when
        creating the Function.  By default, introspection on `func` is used to
        generate a name.
      grad_func: If not None, specifies the gradient function. The
                 gradient function must satisify the criterion defined in
                 function.proto:GradientDef.
      python_grad_func: If not None, specifies the gradient function with the same
                 interface as that expected by `tf.RegisterGradient`. This
                 will be called by tf.gradients to add the gradient ops to the
                 graph. No more than one of {grad_func, python_grad_func} may be
                 specified.
  
    Returns:
      A FunctionDef protocol buffer.
  
    Raises:
      ValueError: if the arguments are invalid.
  
    """
    # TODO(touts): Lift the limitation that func can only receive Tensor args.
    func_name = func_name or _get_func_name(func)
    grad_func_name = _get_func_name(grad_func) if grad_func is not None else None
  
    argspec = inspect.getargspec(func)
    if argspec.keywords or argspec.defaults:
      raise ValueError("Functions with argument defaults or keyword "
                       "arguments are not supported.")
    if inspect.isfunction(func):
      if argspec.varargs and (
          len(argspec.args) > len(input_types)) or not argspec.varargs and (
              len(argspec.args) != len(input_types)):
        raise ValueError("The function has fewer arguments "
                         "than the number of specified input types.")
      argnames = argspec.args
    elif inspect.ismethod(func):
      if argspec.varargs and (
          len(argspec.args) > 1 + len(input_types)) or not argspec.varargs and (
              len(argspec.args) != 1 + len(input_types)):
        raise ValueError("The class function has fewer arguments "
                         "than the number of specified input types.")
      # 1st argument is the "class" type.
      argnames = argspec.args[1:]
  
    args = []
    if isinstance(input_types, (list, tuple)):
      for i in range(len(input_types)):
        argname = argnames[i] if i < len(argnames) else ("arg%d" % i)
        argtype = input_types[i]
        args.append((argname, argtype))
    else:
      for name in argnames:
        if name not in input_types:
          raise ValueError("Missing type for argument: " + name)
        args.append((name, input_types[name]))
  
    # Create the func_def object.
    temp_graph = ops.Graph()
    with temp_graph.as_default():
      # List of placeholders for the function_def.
      inputs = []
      # Arglist to call 'func'
      kwargs = {}
      for (argname, argtype) in args:
        argholder = array_ops.placeholder(argtype, name=argname)
        inputs.append(argholder)
        kwargs[argname] = argholder
      # Call func and gather the output tensors.
      if isinstance(input_types, (list, tuple)):
        outputs = func(*inputs)
      else:
        outputs = func(**kwargs)
      if not isinstance(outputs, ops.Tensor) and not outputs:
        raise ValueError("Function must return at least one tensor")
      # Convenience: if func only returned one value, make it a tuple.
      if not isinstance(outputs, (list, tuple)):
        outputs = (outputs,)
    # Build the FunctionDef
    func_def = graph_to_function_def(temp_graph, func_name, inputs, outputs)
    g = ops.get_default_graph()
    # pylint: disable=protected-access
    g._add_function(func_def, grad_func_name, python_grad_func=python_grad_func)
    # pylint: enable=protected-access
    return func_def
function_tokens: def define_function ( func , input_types , func_name = None , grad_func = None , python_grad_func = None ) : # TODO(touts): Lift the limitation that func can only receive Tensor args. func_name = func_name or _get_func_name ( func ) grad_func_name = _get_func_name ( grad_func ) if grad_func is not None else None argspec = inspect . getargspec ( func ) if argspec . keywords or argspec . defaults : raise ValueError ( "Functions with argument defaults or keyword " "arguments are not supported." ) if inspect . isfunction ( func ) : if argspec . varargs and ( len ( argspec . args ) > len ( input_types ) ) or not argspec . varargs and ( len ( argspec . args ) != len ( input_types ) ) : raise ValueError ( "The function has fewer arguments " "than the number of specified input types." ) argnames = argspec . args elif inspect . ismethod ( func ) : if argspec . varargs and ( len ( argspec . args ) > 1 + len ( input_types ) ) or not argspec . varargs and ( len ( argspec . args ) != 1 + len ( input_types ) ) : raise ValueError ( "The class function has fewer arguments " "than the number of specified input types." ) # 1st argument is the "class" type. argnames = argspec . args [ 1 : ] args = [ ] if isinstance ( input_types , ( list , tuple ) ) : for i in range ( len ( input_types ) ) : argname = argnames [ i ] if i < len ( argnames ) else ( "arg%d" % i ) argtype = input_types [ i ] args . append ( ( argname , argtype ) ) else : for name in argnames : if name not in input_types : raise ValueError ( "Missing type for argument: " + name ) args . append ( ( name , input_types [ name ] ) ) # Create the func_def object. temp_graph = ops . Graph ( ) with temp_graph . as_default ( ) : # List of placeholders for the function_def. inputs = [ ] # Arglist to call 'func' kwargs = { } for ( argname , argtype ) in args : argholder = array_ops . placeholder ( argtype , name = argname ) inputs . append ( argholder ) kwargs [ argname ] = argholder # Call func and gather the output tensors. if isinstance ( input_types , ( list , tuple ) ) : outputs = func ( * inputs ) else : outputs = func ( * * kwargs ) if not isinstance ( outputs , ops . Tensor ) and not outputs : raise ValueError ( "Function must return at least one tensor" ) # Convenience: if func only returned one value, make it a tuple. if not isinstance ( outputs , ( list , tuple ) ) : outputs = ( outputs , ) # Build the FunctionDef func_def = graph_to_function_def ( temp_graph , func_name , inputs , outputs ) g = ops . get_default_graph ( ) # pylint: disable=protected-access g . _add_function ( func_def , grad_func_name , python_grad_func = python_grad_func ) # pylint: enable=protected-access return func_def