using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;

namespace Tensorflow.Operations
{
    public class gen_ops
    {
        static readonly OpDefLibrary _op_def_lib;
        static gen_ops() { _op_def_lib = new OpDefLibrary(); }

        /// <summary>
        ///    Raise a exception to abort the process when called.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Abort'.
        /// </param>
        /// <param name="error_msg">
        ///    A string which is the message associated with the exception.
        /// </param>
        /// <param name="exit_without_error">
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    If exit_without_error is true, the process will exit normally,
        ///    otherwise it will exit with a SIGABORT signal.
        ///    
        ///    Returns nothing but an exception.
        /// </remarks>
        public static Operation abort (string error_msg = null, bool? exit_without_error = null, string name = "Abort")
        {
            var dict = new Dictionary<string, object>();
            if (error_msg != null)
                dict["error_msg"] = error_msg;
            if (exit_without_error.HasValue)
                dict["exit_without_error"] = exit_without_error.Value;
            var op = _op_def_lib._apply_op_helper("Abort", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Computes the absolute value of a tensor.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Abs'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given a tensor <c>x</c>, this operation returns a tensor containing the absolute
        ///    value of each element in <c>x</c>. For example, if x is an input element and y is
        ///    an output element, this operation computes \\(y = |x|\\).
        /// </remarks>
        public static Tensor abs (Tensor x, string name = "Abs")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Abs", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the element-wise sum of a list of tensors.
        /// </summary>
        /// <param name="inputs">
        ///    A list of <c>Tensor</c> objects, each with same shape and type.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AccumulateNV2'.
        /// </param>
        /// <param name="shape">
        ///    Optional argument
        ///    Shape of elements of <c>inputs</c>.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    <c>tf.accumulate_n_v2</c> performs the same operation as <c>tf.add_n</c>, but does not
        ///    wait for all of its inputs to be ready before beginning to sum. This can
        ///    save memory if inputs are ready at different times, since minimum temporary
        ///    storage is proportional to the output size rather than the inputs size.
        ///    
        ///    Unlike the original <c>accumulate_n</c>, <c>accumulate_n_v2</c> is differentiable.
        ///    
        ///    Returns a <c>Tensor</c> of same shape and type as the elements of <c>inputs</c>.
        /// </remarks>
        public static Tensor accumulate_n_v2 (Tensor[] inputs, TensorShape shape, string name = "AccumulateNV2")
        {
            var dict = new Dictionary<string, object>();
            dict["inputs"] = inputs;
            dict["shape"] = shape;
            var op = _op_def_lib._apply_op_helper("AccumulateNV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Applies a gradient to a given accumulator.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a accumulator.
        /// </param>
        /// <param name="local_step">
        ///    The local_step value at which the gradient was computed.
        /// </param>
        /// <param name="gradient">
        ///    A tensor of the gradient to be accumulated.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AccumulatorApplyGradient'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    Does not add if local_step is lesser than the accumulator's global_step.
        /// </remarks>
        public static Operation accumulator_apply_gradient (Tensor handle, Tensor local_step, Tensor gradient, string name = "AccumulatorApplyGradient")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["local_step"] = local_step;
            dict["gradient"] = gradient;
            var op = _op_def_lib._apply_op_helper("AccumulatorApplyGradient", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Returns the number of gradients aggregated in the given accumulators.
        /// </summary>
        /// <param name="handle">
        ///    The handle to an accumulator.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AccumulatorNumAccumulated'.
        /// </param>
        /// <returns>
        ///    The number of gradients aggregated in the given accumulator.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor accumulator_num_accumulated (Tensor handle, string name = "AccumulatorNumAccumulated")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            var op = _op_def_lib._apply_op_helper("AccumulatorNumAccumulated", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Updates the accumulator with a new value for global_step.
        /// </summary>
        /// <param name="handle">
        ///    The handle to an accumulator.
        /// </param>
        /// <param name="new_global_step">
        ///    The new global_step value to set.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AccumulatorSetGlobalStep'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    Logs warning if the accumulator's value is already higher than
        ///    new_global_step.
        /// </remarks>
        public static Operation accumulator_set_global_step (Tensor handle, Tensor new_global_step, string name = "AccumulatorSetGlobalStep")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["new_global_step"] = new_global_step;
            var op = _op_def_lib._apply_op_helper("AccumulatorSetGlobalStep", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Extracts the average gradient in the given ConditionalAccumulator.
        /// </summary>
        /// <param name="handle">
        ///    The handle to an accumulator.
        /// </param>
        /// <param name="num_required">
        ///    Number of gradients required before we return an aggregate.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AccumulatorTakeGradient'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The data type of accumulated gradients. Needs to correspond to the type
        ///    of the accumulator.
        /// </param>
        /// <returns>
        ///    The average of the accumulated gradients.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The op blocks until sufficient (i.e., more than num_required)
        ///    gradients have been accumulated.  If the accumulator has already
        ///    aggregated more than num_required gradients, it returns the average of
        ///    the accumulated gradients.  Also automatically increments the recorded
        ///    global_step in the accumulator by 1, and resets the aggregate to 0.
        /// </remarks>
        public static Tensor accumulator_take_gradient (Tensor handle, Tensor num_required, TF_DataType dtype, string name = "AccumulatorTakeGradient")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["num_required"] = num_required;
            dict["dtype"] = dtype;
            var op = _op_def_lib._apply_op_helper("AccumulatorTakeGradient", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes acos of x element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Acos'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor acos (Tensor x, string name = "Acos")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Acos", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes inverse hyperbolic cosine of x element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Acosh'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor acosh (Tensor x, string name = "Acosh")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Acosh", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns x + y element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Add'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    *NOTE*: <c>Add</c> supports broadcasting. <c>AddN</c> does not. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor add (Tensor x, Tensor y, string name = "Add")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("Add", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Add an <c>N</c>-minibatch <c>SparseTensor</c> to a <c>SparseTensorsMap</c>, return <c>N</c> handles.
        /// </summary>
        /// <param name="sparse_indices">
        ///    2-D.  The <c>indices</c> of the minibatch <c>SparseTensor</c>.
        ///    <c>sparse_indices[:, 0]</c> must be ordered values in <c>[0, N)</c>.
        /// </param>
        /// <param name="sparse_values">
        ///    1-D.  The <c>values</c> of the minibatch <c>SparseTensor</c>.
        /// </param>
        /// <param name="sparse_shape">
        ///    1-D.  The <c>shape</c> of the minibatch <c>SparseTensor</c>.
        ///    The minibatch size <c>N == sparse_shape[0]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AddManySparseToTensorsMap'.
        /// </param>
        /// <param name="container">
        ///    The container name for the <c>SparseTensorsMap</c> created by this op.
        /// </param>
        /// <param name="shared_name">
        ///    The shared name for the <c>SparseTensorsMap</c> created by this op.
        ///    If blank, the new Operation's unique name is used.
        /// </param>
        /// <returns>
        ///    1-D.  The handles of the <c>SparseTensor</c> now stored in the
        ///    <c>SparseTensorsMap</c>.  Shape: <c>[N]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    A <c>SparseTensor</c> of rank <c>R</c> is represented by three tensors: <c>sparse_indices</c>,
        ///    <c>sparse_values</c>, and <c>sparse_shape</c>, where
        ///    
        ///   <code>
        ///    sparse_indices.shape[1] == sparse_shape.shape[0] == R
        ///    </code>
        ///    
        ///    An <c>N</c>-minibatch of <c>SparseTensor</c> objects is represented as a <c>SparseTensor</c>
        ///    having a first <c>sparse_indices</c> column taking values between <c>[0, N)</c>, where
        ///    the minibatch size <c>N == sparse_shape[0]</c>.
        ///    
        ///    The input <c>SparseTensor</c> must have rank <c>R</c> greater than 1, and the first
        ///    dimension is treated as the minibatch dimension.  Elements of the <c>SparseTensor</c>
        ///    must be sorted in increasing order of this first dimension.  The stored
        ///    <c>SparseTensor</c> objects pointed to by each row of the output <c>sparse_handles</c>
        ///    will have rank <c>R-1</c>.
        ///    
        ///    The <c>SparseTensor</c> values can then be read out as part of a minibatch by passing
        ///    the given keys as vector elements to <c>TakeManySparseFromTensorsMap</c>.  To ensure
        ///    the correct <c>SparseTensorsMap</c> is accessed, ensure that the same
        ///    <c>container</c> and <c>shared_name</c> are passed to that Op.  If no <c>shared_name</c>
        ///    is provided here, instead use the *name* of the Operation created by calling
        ///    <c>AddManySparseToTensorsMap</c> as the <c>shared_name</c> passed to
        ///    <c>TakeManySparseFromTensorsMap</c>.  Ensure the Operations are colocated.
        /// </remarks>
        public static Tensor add_many_sparse_to_tensors_map (Tensor sparse_indices, Tensor sparse_values, Tensor sparse_shape, string container = null, string shared_name = null, string name = "AddManySparseToTensorsMap")
        {
            var dict = new Dictionary<string, object>();
            dict["sparse_indices"] = sparse_indices;
            dict["sparse_values"] = sparse_values;
            dict["sparse_shape"] = sparse_shape;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("AddManySparseToTensorsMap", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Add all input tensors element wise.
        /// </summary>
        /// <param name="inputs">
        ///    Must all be the same size and shape.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AddN'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor add_n (Tensor[] inputs, string name = "AddN")
        {
            var dict = new Dictionary<string, object>();
            dict["inputs"] = inputs;
            var op = _op_def_lib._apply_op_helper("AddN", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Add a <c>SparseTensor</c> to a <c>SparseTensorsMap</c> return its handle.
        /// </summary>
        /// <param name="sparse_indices">
        ///    2-D.  The <c>indices</c> of the <c>SparseTensor</c>.
        /// </param>
        /// <param name="sparse_values">
        ///    1-D.  The <c>values</c> of the <c>SparseTensor</c>.
        /// </param>
        /// <param name="sparse_shape">
        ///    1-D.  The <c>shape</c> of the <c>SparseTensor</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AddSparseToTensorsMap'.
        /// </param>
        /// <param name="container">
        ///    The container name for the <c>SparseTensorsMap</c> created by this op.
        /// </param>
        /// <param name="shared_name">
        ///    The shared name for the <c>SparseTensorsMap</c> created by this op.
        ///    If blank, the new Operation's unique name is used.
        /// </param>
        /// <returns>
        ///    0-D.  The handle of the <c>SparseTensor</c> now stored in the
        ///    <c>SparseTensorsMap</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    A <c>SparseTensor</c> is represented by three tensors: <c>sparse_indices</c>,
        ///    <c>sparse_values</c>, and <c>sparse_shape</c>.
        ///    
        ///    This operator takes the given <c>SparseTensor</c> and adds it to a container
        ///    object (a <c>SparseTensorsMap</c>).  A unique key within this container is generated
        ///    in the form of an <c>int64</c>, and this is the value that is returned.
        ///    
        ///    The <c>SparseTensor</c> can then be read out as part of a minibatch by passing
        ///    the key as a vector element to <c>TakeManySparseFromTensorsMap</c>.  To ensure
        ///    the correct <c>SparseTensorsMap</c> is accessed, ensure that the same
        ///    <c>container</c> and <c>shared_name</c> are passed to that Op.  If no <c>shared_name</c>
        ///    is provided here, instead use the *name* of the Operation created by calling
        ///    <c>AddSparseToTensorsMap</c> as the <c>shared_name</c> passed to
        ///    <c>TakeManySparseFromTensorsMap</c>.  Ensure the Operations are colocated.
        /// </remarks>
        public static Tensor add_sparse_to_tensors_map (Tensor sparse_indices, Tensor sparse_values, Tensor sparse_shape, string container = null, string shared_name = null, string name = "AddSparseToTensorsMap")
        {
            var dict = new Dictionary<string, object>();
            dict["sparse_indices"] = sparse_indices;
            dict["sparse_values"] = sparse_values;
            dict["sparse_shape"] = sparse_shape;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("AddSparseToTensorsMap", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns x + y element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AddV2'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    *NOTE*: <c>Add</c> supports broadcasting. <c>AddN</c> does not. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor add_v2 (Tensor x, Tensor y, string name = "AddV2")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("AddV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Deprecated. Disallowed in GraphDef version &amp;gt;= 2.
        /// </summary>
        /// <param name="images">
        /// </param>
        /// <param name="contrast_factor">
        /// </param>
        /// <param name="min_value">
        /// </param>
        /// <param name="max_value">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AdjustContrast'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor adjust_contrast (Tensor images, Tensor contrast_factor, Tensor min_value, Tensor max_value, string name = "AdjustContrast")
        {
            var dict = new Dictionary<string, object>();
            dict["images"] = images;
            dict["contrast_factor"] = contrast_factor;
            dict["min_value"] = min_value;
            dict["max_value"] = max_value;
            var op = _op_def_lib._apply_op_helper("AdjustContrast", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Adjust the contrast of one or more images.
        /// </summary>
        /// <param name="images">
        ///    Images to adjust.  At least 3-D.
        /// </param>
        /// <param name="contrast_factor">
        ///    A float multiplier for adjusting contrast.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AdjustContrastv2'.
        /// </param>
        /// <returns>
        ///    The contrast-adjusted image or images.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    <c>images</c> is a tensor of at least 3 dimensions.  The last 3 dimensions are
        ///    interpreted as <c>[height, width, channels]</c>.  The other dimensions only
        ///    represent a collection of images, such as <c>[batch, height, width, channels].</c>
        ///    
        ///    Contrast is adjusted independently for each channel of each image.
        ///    
        ///    For each channel, the Op first computes the mean of the image pixels in the
        ///    channel and then adjusts each component of each pixel to
        ///    <c>(x - mean) * contrast_factor + mean</c>.
        /// </remarks>
        public static Tensor adjust_contrastv2 (Tensor images, Tensor contrast_factor, string name = "AdjustContrastv2")
        {
            var dict = new Dictionary<string, object>();
            dict["images"] = images;
            dict["contrast_factor"] = contrast_factor;
            var op = _op_def_lib._apply_op_helper("AdjustContrastv2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Adjust the hue of one or more images.
        /// </summary>
        /// <param name="images">
        ///    Images to adjust.  At least 3-D.
        /// </param>
        /// <param name="delta">
        ///    A float delta to add to the hue.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AdjustHue'.
        /// </param>
        /// <returns>
        ///    The hue-adjusted image or images.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    <c>images</c> is a tensor of at least 3 dimensions.  The last dimension is
        ///    interpretted as channels, and must be three.
        ///    
        ///    The input image is considered in the RGB colorspace. Conceptually, the RGB
        ///    colors are first mapped into HSV. A delta is then applied all the hue values,
        ///    and then remapped back to RGB colorspace.
        /// </remarks>
        public static Tensor adjust_hue (Tensor images, Tensor delta, string name = "AdjustHue")
        {
            var dict = new Dictionary<string, object>();
            dict["images"] = images;
            dict["delta"] = delta;
            var op = _op_def_lib._apply_op_helper("AdjustHue", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Adjust the saturation of one or more images.
        /// </summary>
        /// <param name="images">
        ///    Images to adjust.  At least 3-D.
        /// </param>
        /// <param name="scale">
        ///    A float scale to add to the saturation.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AdjustSaturation'.
        /// </param>
        /// <returns>
        ///    The hue-adjusted image or images.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    <c>images</c> is a tensor of at least 3 dimensions.  The last dimension is
        ///    interpretted as channels, and must be three.
        ///    
        ///    The input image is considered in the RGB colorspace. Conceptually, the RGB
        ///    colors are first mapped into HSV. A scale is then applied all the saturation
        ///    values, and then remapped back to RGB colorspace.
        /// </remarks>
        public static Tensor adjust_saturation (Tensor images, Tensor scale, string name = "AdjustSaturation")
        {
            var dict = new Dictionary<string, object>();
            dict["images"] = images;
            dict["scale"] = scale;
            var op = _op_def_lib._apply_op_helper("AdjustSaturation", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the "logical and" of elements across dimensions of a tensor.
        /// </summary>
        /// <param name="input">
        ///    The tensor to reduce.
        /// </param>
        /// <param name="reduction_indices">
        ///    The dimensions to reduce. Must be in the range
        ///    <c>[-rank(input), rank(input))</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'All'.
        /// </param>
        /// <param name="keep_dims">
        ///    If true, retain reduced dimensions with length 1.
        /// </param>
        /// <returns>
        ///    The reduced tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Reduces <c>input</c> along the dimensions given in <c>axis</c>. Unless
        ///    <c>keep_dims</c> is true, the rank of the tensor is reduced by 1 for each entry in
        ///    <c>axis</c>. If <c>keep_dims</c> is true, the reduced dimensions are
        ///    retained with length 1.
        /// </remarks>
        public static Tensor all (Tensor input, Tensor reduction_indices, bool? keep_dims = null, string name = "All")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["reduction_indices"] = reduction_indices;
            if (keep_dims.HasValue)
                dict["keep_dims"] = keep_dims.Value;
            var op = _op_def_lib._apply_op_helper("All", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Generates labels for candidate sampling with a learned unigram distribution.
        /// </summary>
        /// <param name="true_classes">
        ///    A batch_size * num_true matrix, in which each row contains the
        ///    IDs of the num_true target_classes in the corresponding original label.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AllCandidateSampler'.
        /// </param>
        /// <param name="num_true">
        ///    Optional argument
        ///    Number of true labels per context.
        /// </param>
        /// <param name="num_sampled">
        ///    Optional argument
        ///    Number of candidates to produce.
        /// </param>
        /// <param name="unique">
        ///    Optional argument
        ///    If unique is true, we sample with rejection, so that all sampled
        ///    candidates in a batch are unique. This requires some approximation to
        ///    estimate the post-rejection sampling probabilities.
        /// </param>
        /// <param name="seed">
        ///    If either seed or seed2 are set to be non-zero, the random number
        ///    generator is seeded by the given seed.  Otherwise, it is seeded by a
        ///    random seed.
        /// </param>
        /// <param name="seed2">
        ///    An second seed to avoid seed collision.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    sampled_candidates : A vector of length num_sampled, in which each element is
        ///    the ID of a sampled candidate.
        ///    true_expected_count : A batch_size * num_true matrix, representing
        ///    the number of times each candidate is expected to occur in a batch
        ///    of sampled candidates. If unique=true, then this is a probability.
        ///    sampled_expected_count : A vector of length num_sampled, for each sampled
        ///    candidate representing the number of times the candidate is expected
        ///    to occur in a batch of sampled candidates.  If unique=true, then this is a
        ///    probability.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    See explanations of candidate sampling and the data formats at
        ///    go/candidate-sampling.
        ///    
        ///    For each batch, this op picks a single set of sampled candidate labels.
        ///    
        ///    The advantages of sampling candidates per-batch are simplicity and the
        ///    possibility of efficient dense matrix multiplication. The disadvantage is that
        ///    the sampled candidates must be chosen independently of the context and of the
        ///    true labels.
        /// </remarks>
        public static (Tensor sampled_candidates, Tensor true_expected_count, Tensor sampled_expected_count) all_candidate_sampler (Tensor true_classes, int num_true, int num_sampled, bool unique, int? seed = null, int? seed2 = null, string name = "AllCandidateSampler")
        {
            var dict = new Dictionary<string, object>();
            dict["true_classes"] = true_classes;
            dict["num_true"] = num_true;
            dict["num_sampled"] = num_sampled;
            dict["unique"] = unique;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("AllCandidateSampler", name: name, keywords: dict);
            int _idx = 0;
            var sampled_candidates = op.outputs[_idx++];
            var true_expected_count = op.outputs[_idx++];
            var sampled_expected_count = op.outputs[_idx++];
            return (sampled_candidates, true_expected_count, sampled_expected_count);
        }

        /// <summary>
        ///    Returns the argument of a complex number.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Angle'.
        /// </param>
        /// <param name="Tout">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given a tensor <c>input</c> of complex numbers, this operation returns a tensor of
        ///    type <c>float</c> that is the argument of each element in <c>input</c>. All elements in
        ///    <c>input</c> must be complex numbers of the form \\(a + bj\\), where *a*
        ///    is the real part and *b* is the imaginary part.
        ///    
        ///    The argument returned by this operation is of the form \\(atan2(b, a)\\).
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # tensor 'input' is [-2.25 + 4.75j, 3.25 + 5.75j]
        ///    tf.angle(input) ==&amp;gt; [2.0132, 1.056]
        ///   </code>
        ///    
        ///    @compatibility(numpy)
        ///    Equivalent to np.angle.
        ///    @end_compatibility
        /// </remarks>
        public static Tensor angle (Tensor input, TF_DataType? Tout = null, string name = "Angle")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (Tout.HasValue)
                dict["Tout"] = Tout.Value;
            var op = _op_def_lib._apply_op_helper("Angle", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A container for an iterator resource.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AnonymousIterator'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    A handle to the iterator that can be passed to a "MakeIterator" or
        ///    "IteratorGetNext" op. In contrast to Iterator, AnonymousIterator prevents
        ///    resource sharing by name, and does not keep a reference to the resource
        ///    container.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor anonymous_iterator (TF_DataType[] output_types, TensorShape[] output_shapes, string name = "AnonymousIterator")
        {
            var dict = new Dictionary<string, object>();
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("AnonymousIterator", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the "logical or" of elements across dimensions of a tensor.
        /// </summary>
        /// <param name="input">
        ///    The tensor to reduce.
        /// </param>
        /// <param name="reduction_indices">
        ///    The dimensions to reduce. Must be in the range
        ///    <c>[-rank(input), rank(input))</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Any'.
        /// </param>
        /// <param name="keep_dims">
        ///    If true, retain reduced dimensions with length 1.
        /// </param>
        /// <returns>
        ///    The reduced tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Reduces <c>input</c> along the dimensions given in <c>axis</c>. Unless
        ///    <c>keep_dims</c> is true, the rank of the tensor is reduced by 1 for each entry in
        ///    <c>axis</c>. If <c>keep_dims</c> is true, the reduced dimensions are
        ///    retained with length 1.
        /// </remarks>
        public static Tensor any (Tensor input, Tensor reduction_indices, bool? keep_dims = null, string name = "Any")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["reduction_indices"] = reduction_indices;
            if (keep_dims.HasValue)
                dict["keep_dims"] = keep_dims.Value;
            var op = _op_def_lib._apply_op_helper("Any", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update '*var' according to the AdaMax algorithm.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="m">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="v">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="beta1_power">
        ///    Must be a scalar.
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="beta1">
        ///    Momentum factor. Must be a scalar.
        /// </param>
        /// <param name="beta2">
        ///    Momentum factor. Must be a scalar.
        /// </param>
        /// <param name="epsilon">
        ///    Ridge term. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ApplyAdaMax'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var, m, and v tensors will be protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    m_t &amp;lt;- beta1 * m_{t-1} + (1 - beta1) * g
        ///    v_t &amp;lt;- max(beta2 * v_{t-1}, abs(g))
        ///    variable &amp;lt;- variable - learning_rate / (1 - beta1^t) * m_t / (v_t + epsilon)
        /// </remarks>
        public static Tensor apply_ada_max (Tensor var, Tensor m, Tensor v, Tensor beta1_power, Tensor lr, Tensor beta1, Tensor beta2, Tensor epsilon, Tensor grad, bool? use_locking = null, string name = "ApplyAdaMax")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["m"] = m;
            dict["v"] = v;
            dict["beta1_power"] = beta1_power;
            dict["lr"] = lr;
            dict["beta1"] = beta1;
            dict["beta2"] = beta2;
            dict["epsilon"] = epsilon;
            dict["grad"] = grad;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ApplyAdaMax", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update '*var' according to the adadelta scheme.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum_update">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="rho">
        ///    Decay factor. Must be a scalar.
        /// </param>
        /// <param name="epsilon">
        ///    Constant factor. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ApplyAdadelta'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, updating of the var, accum and update_accum tensors will be protected by
        ///    a lock; otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    accum = rho() * accum + (1 - rho()) * grad.square();
        ///    update = (update_accum + epsilon).sqrt() * (accum + epsilon()).rsqrt() * grad;
        ///    update_accum = rho() * update_accum + (1 - rho()) * update.square();
        ///    var -= update;
        /// </remarks>
        public static Tensor apply_adadelta (Tensor var, Tensor accum, Tensor accum_update, Tensor lr, Tensor rho, Tensor epsilon, Tensor grad, bool? use_locking = null, string name = "ApplyAdadelta")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["accum_update"] = accum_update;
            dict["lr"] = lr;
            dict["rho"] = rho;
            dict["epsilon"] = epsilon;
            dict["grad"] = grad;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ApplyAdadelta", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update '*var' according to the adagrad scheme.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ApplyAdagrad'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var and accum tensors will be protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <param name="update_slots">
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    accum += grad * grad
        ///    var -= lr * grad * (1 / sqrt(accum))
        /// </remarks>
        public static Tensor apply_adagrad (Tensor var, Tensor accum, Tensor lr, Tensor grad, bool? use_locking = null, bool? update_slots = null, string name = "ApplyAdagrad")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["lr"] = lr;
            dict["grad"] = grad;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            if (update_slots.HasValue)
                dict["update_slots"] = update_slots.Value;
            var op = _op_def_lib._apply_op_helper("ApplyAdagrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update '*var' according to the proximal adagrad scheme.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="gradient_accumulator">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="gradient_squared_accumulator">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="l1">
        ///    L1 regularization. Must be a scalar.
        /// </param>
        /// <param name="l2">
        ///    L2 regularization. Must be a scalar.
        /// </param>
        /// <param name="global_step">
        ///    Training step number. Must be a scalar.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ApplyAdagradDA'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, updating of the var and accum tensors will be protected by
        ///    a lock; otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor apply_adagrad_d_a (Tensor var, Tensor gradient_accumulator, Tensor gradient_squared_accumulator, Tensor grad, Tensor lr, Tensor l1, Tensor l2, Tensor global_step, bool? use_locking = null, string name = "ApplyAdagradDA")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["gradient_accumulator"] = gradient_accumulator;
            dict["gradient_squared_accumulator"] = gradient_squared_accumulator;
            dict["grad"] = grad;
            dict["lr"] = lr;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["global_step"] = global_step;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ApplyAdagradDA", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update '*var' according to the Adam algorithm.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="m">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="v">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="beta1_power">
        ///    Must be a scalar.
        /// </param>
        /// <param name="beta2_power">
        ///    Must be a scalar.
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="beta1">
        ///    Momentum factor. Must be a scalar.
        /// </param>
        /// <param name="beta2">
        ///    Momentum factor. Must be a scalar.
        /// </param>
        /// <param name="epsilon">
        ///    Ridge term. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ApplyAdam'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var, m, and v tensors will be protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <param name="use_nesterov">
        ///    If <c>True</c>, uses the nesterov update.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    $$lr_t := \text{learning\_rate} * \sqrt{1 - beta_2^t} / (1 - beta_1^t)$$
        ///    $$m_t := beta_1 * m_{t-1} + (1 - beta_1) * g$$
        ///    $$v_t := beta_2 * v_{t-1} + (1 - beta_2) * g * g$$
        ///    $$variable := variable - lr_t * m_t / (\sqrt{v_t} + \epsilon)$$
        /// </remarks>
        public static Tensor apply_adam (Tensor var, Tensor m, Tensor v, Tensor beta1_power, Tensor beta2_power, Tensor lr, Tensor beta1, Tensor beta2, Tensor epsilon, Tensor grad, bool? use_locking = null, bool? use_nesterov = null, string name = "ApplyAdam")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["m"] = m;
            dict["v"] = v;
            dict["beta1_power"] = beta1_power;
            dict["beta2_power"] = beta2_power;
            dict["lr"] = lr;
            dict["beta1"] = beta1;
            dict["beta2"] = beta2;
            dict["epsilon"] = epsilon;
            dict["grad"] = grad;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            if (use_nesterov.HasValue)
                dict["use_nesterov"] = use_nesterov.Value;
            var op = _op_def_lib._apply_op_helper("ApplyAdam", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update '*var' according to the AddSign update.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="m">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="alpha">
        ///    Must be a scalar.
        /// </param>
        /// <param name="sign_decay">
        ///    Must be a scalar.
        /// </param>
        /// <param name="beta">
        ///    Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ApplyAddSign'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var and m tensors is
        ///    protected by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    m_t &amp;lt;- beta1 * m_{t-1} + (1 - beta1) * g
        ///    update &amp;lt;- (alpha + sign_decay * sign(g) *sign(m)) * g
        ///    variable &amp;lt;- variable - lr_t * update
        /// </remarks>
        public static Tensor apply_add_sign (Tensor var, Tensor m, Tensor lr, Tensor alpha, Tensor sign_decay, Tensor beta, Tensor grad, bool? use_locking = null, string name = "ApplyAddSign")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["m"] = m;
            dict["lr"] = lr;
            dict["alpha"] = alpha;
            dict["sign_decay"] = sign_decay;
            dict["beta"] = beta;
            dict["grad"] = grad;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ApplyAddSign", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update '*var' according to the centered RMSProp algorithm.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="mg">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="ms">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="mom">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="rho">
        ///    Decay rate. Must be a scalar.
        /// </param>
        /// <param name="momentum">
        /// </param>
        /// <param name="epsilon">
        ///    Ridge term. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ApplyCenteredRMSProp'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var, mg, ms, and mom tensors is
        ///    protected by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The centered RMSProp algorithm uses an estimate of the centered second moment
        ///    (i.e., the variance) for normalization, as opposed to regular RMSProp, which
        ///    uses the (uncentered) second moment. This often helps with training, but is
        ///    slightly more expensive in terms of computation and memory.
        ///    
        ///    Note that in dense implementation of this algorithm, mg, ms, and mom will
        ///    update even if the grad is zero, but in this sparse implementation, mg, ms,
        ///    and mom will not update in iterations during which the grad is zero.
        ///    
        ///    mean_square = decay * mean_square + (1-decay) * gradient ** 2
        ///    mean_grad = decay * mean_grad + (1-decay) * gradient
        ///    
        ///    Delta = learning_rate * gradient / sqrt(mean_square + epsilon - mean_grad ** 2)
        ///    
        ///    mg &amp;lt;- rho * mg_{t-1} + (1-rho) * grad
        ///    ms &amp;lt;- rho * ms_{t-1} + (1-rho) * grad * grad
        ///    mom &amp;lt;- momentum * mom_{t-1} + lr * grad / sqrt(ms - mg * mg + epsilon)
        ///    var &amp;lt;- var - mom
        /// </remarks>
        public static Tensor apply_centered_r_m_s_prop (Tensor var, Tensor mg, Tensor ms, Tensor mom, Tensor lr, Tensor rho, Tensor momentum, Tensor epsilon, Tensor grad, bool? use_locking = null, string name = "ApplyCenteredRMSProp")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["mg"] = mg;
            dict["ms"] = ms;
            dict["mom"] = mom;
            dict["lr"] = lr;
            dict["rho"] = rho;
            dict["momentum"] = momentum;
            dict["epsilon"] = epsilon;
            dict["grad"] = grad;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ApplyCenteredRMSProp", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update '*var' according to the Ftrl-proximal scheme.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="linear">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="l1">
        ///    L1 regulariation. Must be a scalar.
        /// </param>
        /// <param name="l2">
        ///    L2 regulariation. Must be a scalar.
        /// </param>
        /// <param name="lr_power">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ApplyFtrl'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var and accum tensors will be protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    accum_new = accum + grad * grad
        ///    linear += grad + (accum_new^(-lr_power) - accum^(-lr_power)) / lr * var
        ///    quadratic = 1.0 / (accum_new^(lr_power) * lr) + 2 * l2
        ///    var = (sign(linear) * l1 - linear) / quadratic if |linear| &amp;gt; l1 else 0.0
        ///    accum = accum_new
        /// </remarks>
        public static Tensor apply_ftrl (Tensor var, Tensor accum, Tensor linear, Tensor grad, Tensor lr, Tensor l1, Tensor l2, Tensor lr_power, bool? use_locking = null, string name = "ApplyFtrl")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["linear"] = linear;
            dict["grad"] = grad;
            dict["lr"] = lr;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["lr_power"] = lr_power;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ApplyFtrl", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update '*var' according to the Ftrl-proximal scheme.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="linear">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="l1">
        ///    L1 regulariation. Must be a scalar.
        /// </param>
        /// <param name="l2">
        ///    L2 shrinkage regulariation. Must be a scalar.
        /// </param>
        /// <param name="l2_shrinkage">
        /// </param>
        /// <param name="lr_power">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ApplyFtrlV2'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var and accum tensors will be protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    grad_with_shrinkage = grad + 2 * l2_shrinkage * var
        ///    accum_new = accum + grad_with_shrinkage * grad_with_shrinkage
        ///    linear += grad_with_shrinkage +
        ///    (accum_new^(-lr_power) - accum^(-lr_power)) / lr * var
        ///    quadratic = 1.0 / (accum_new^(lr_power) * lr) + 2 * l2
        ///    var = (sign(linear) * l1 - linear) / quadratic if |linear| &amp;gt; l1 else 0.0
        ///    accum = accum_new
        /// </remarks>
        public static Tensor apply_ftrl_v2 (Tensor var, Tensor accum, Tensor linear, Tensor grad, Tensor lr, Tensor l1, Tensor l2, Tensor l2_shrinkage, Tensor lr_power, bool? use_locking = null, string name = "ApplyFtrlV2")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["linear"] = linear;
            dict["grad"] = grad;
            dict["lr"] = lr;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["l2_shrinkage"] = l2_shrinkage;
            dict["lr_power"] = lr_power;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ApplyFtrlV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update '*var' by subtracting 'alpha' * 'delta' from it.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="alpha">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="delta">
        ///    The change.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ApplyGradientDescent'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, the subtraction will be protected by a lock;
        ///    otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor apply_gradient_descent (Tensor var, Tensor alpha, Tensor delta, bool? use_locking = null, string name = "ApplyGradientDescent")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["alpha"] = alpha;
            dict["delta"] = delta;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ApplyGradientDescent", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update '*var' according to the momentum scheme. Set use_nesterov = True if you
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="momentum">
        ///    Momentum. Must be a scalar.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ApplyMomentum'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var and accum tensors will be protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <param name="use_nesterov">
        ///    If <c>True</c>, the tensor passed to compute grad will be
        ///    var - lr * momentum * accum, so in the end, the var you get is actually
        ///    var - lr * momentum * accum.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    want to use Nesterov momentum.
        ///    
        ///    accum = accum * momentum + grad
        ///    var -= lr * accum
        /// </remarks>
        public static Tensor apply_momentum (Tensor var, Tensor accum, Tensor lr, Tensor grad, Tensor momentum, bool? use_locking = null, bool? use_nesterov = null, string name = "ApplyMomentum")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["lr"] = lr;
            dict["grad"] = grad;
            dict["momentum"] = momentum;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            if (use_nesterov.HasValue)
                dict["use_nesterov"] = use_nesterov.Value;
            var op = _op_def_lib._apply_op_helper("ApplyMomentum", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update '*var' according to the AddSign update.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="m">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="logbase">
        ///    Must be a scalar.
        /// </param>
        /// <param name="sign_decay">
        ///    Must be a scalar.
        /// </param>
        /// <param name="beta">
        ///    Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ApplyPowerSign'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var and m tensors is
        ///    protected by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    m_t &amp;lt;- beta1 * m_{t-1} + (1 - beta1) * g
        ///    update &amp;lt;- exp(logbase * sign_decay * sign(g) * sign(m_t)) * g
        ///    variable &amp;lt;- variable - lr_t * update
        /// </remarks>
        public static Tensor apply_power_sign (Tensor var, Tensor m, Tensor lr, Tensor logbase, Tensor sign_decay, Tensor beta, Tensor grad, bool? use_locking = null, string name = "ApplyPowerSign")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["m"] = m;
            dict["lr"] = lr;
            dict["logbase"] = logbase;
            dict["sign_decay"] = sign_decay;
            dict["beta"] = beta;
            dict["grad"] = grad;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ApplyPowerSign", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update '*var' and '*accum' according to FOBOS with Adagrad learning rate.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="l1">
        ///    L1 regularization. Must be a scalar.
        /// </param>
        /// <param name="l2">
        ///    L2 regularization. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ApplyProximalAdagrad'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, updating of the var and accum tensors will be protected by
        ///    a lock; otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    accum += grad * grad
        ///    prox_v = var - lr * grad * (1 / sqrt(accum))
        ///    var = sign(prox_v)/(1+lr*l2) * max{|prox_v|-lr*l1,0}
        /// </remarks>
        public static Tensor apply_proximal_adagrad (Tensor var, Tensor accum, Tensor lr, Tensor l1, Tensor l2, Tensor grad, bool? use_locking = null, string name = "ApplyProximalAdagrad")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["lr"] = lr;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["grad"] = grad;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ApplyProximalAdagrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update '*var' as FOBOS algorithm with fixed learning rate.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="alpha">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="l1">
        ///    L1 regularization. Must be a scalar.
        /// </param>
        /// <param name="l2">
        ///    L2 regularization. Must be a scalar.
        /// </param>
        /// <param name="delta">
        ///    The change.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ApplyProximalGradientDescent'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, the subtraction will be protected by a lock;
        ///    otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    prox_v = var - alpha * delta
        ///    var = sign(prox_v)/(1+alpha*l2) * max{|prox_v|-alpha*l1,0}
        /// </remarks>
        public static Tensor apply_proximal_gradient_descent (Tensor var, Tensor alpha, Tensor l1, Tensor l2, Tensor delta, bool? use_locking = null, string name = "ApplyProximalGradientDescent")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["alpha"] = alpha;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["delta"] = delta;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ApplyProximalGradientDescent", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update '*var' according to the RMSProp algorithm.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="ms">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="mom">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="rho">
        ///    Decay rate. Must be a scalar.
        /// </param>
        /// <param name="momentum">
        /// </param>
        /// <param name="epsilon">
        ///    Ridge term. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ApplyRMSProp'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var, ms, and mom tensors is protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Note that in dense implementation of this algorithm, ms and mom will
        ///    update even if the grad is zero, but in this sparse implementation, ms
        ///    and mom will not update in iterations during which the grad is zero.
        ///    
        ///    mean_square = decay * mean_square + (1-decay) * gradient ** 2
        ///    Delta = learning_rate * gradient / sqrt(mean_square + epsilon)
        ///    
        ///    ms &amp;lt;- rho * ms_{t-1} + (1-rho) * grad * grad
        ///    mom &amp;lt;- momentum * mom_{t-1} + lr * grad / sqrt(ms + epsilon)
        ///    var &amp;lt;- var - mom
        /// </remarks>
        public static Tensor apply_r_m_s_prop (Tensor var, Tensor ms, Tensor mom, Tensor lr, Tensor rho, Tensor momentum, Tensor epsilon, Tensor grad, bool? use_locking = null, string name = "ApplyRMSProp")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["ms"] = ms;
            dict["mom"] = mom;
            dict["lr"] = lr;
            dict["rho"] = rho;
            dict["momentum"] = momentum;
            dict["epsilon"] = epsilon;
            dict["grad"] = grad;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ApplyRMSProp", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the truth value of abs(x-y) &amp;lt; tolerance element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ApproximateEqual'.
        /// </param>
        /// <param name="tolerance">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor approximate_equal (Tensor x, Tensor y, float? tolerance = null, string name = "ApproximateEqual")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            if (tolerance.HasValue)
                dict["tolerance"] = tolerance.Value;
            var op = _op_def_lib._apply_op_helper("ApproximateEqual", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the index with the largest value across dimensions of a tensor.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="dimension">
        ///    int32 or int64, must be in the range <c>[-rank(input), rank(input))</c>.
        ///    Describes which dimension of the input Tensor to reduce across. For vectors,
        ///    use dimension = 0.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ArgMax'.
        /// </param>
        /// <param name="output_type">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Note that in case of ties the identity of the return value is not guaranteed.
        /// </remarks>
        public static Tensor arg_max (Tensor input, Tensor dimension, TF_DataType? output_type = null, string name = "ArgMax")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["dimension"] = dimension;
            if (output_type.HasValue)
                dict["output_type"] = output_type.Value;
            var op = _op_def_lib._apply_op_helper("ArgMax", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the index with the smallest value across dimensions of a tensor.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="dimension">
        ///    int32 or int64, must be in the range <c>[-rank(input), rank(input))</c>.
        ///    Describes which dimension of the input Tensor to reduce across. For vectors,
        ///    use dimension = 0.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ArgMin'.
        /// </param>
        /// <param name="output_type">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Note that in case of ties the identity of the return value is not guaranteed.
        /// </remarks>
        public static Tensor arg_min (Tensor input, Tensor dimension, TF_DataType? output_type = null, string name = "ArgMin")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["dimension"] = dimension;
            if (output_type.HasValue)
                dict["output_type"] = output_type.Value;
            var op = _op_def_lib._apply_op_helper("ArgMin", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Converts each entry in the given tensor to strings.  Supports many numeric
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AsString'.
        /// </param>
        /// <param name="precision">
        ///    The post-decimal precision to use for floating point numbers.
        ///    Only used if precision &amp;gt; -1.
        /// </param>
        /// <param name="scientific">
        ///    Use scientific notation for floating point numbers.
        /// </param>
        /// <param name="shortest">
        ///    Use shortest representation (either scientific or standard) for
        ///    floating point numbers.
        /// </param>
        /// <param name="width">
        ///    Pad pre-decimal numbers to this width.
        ///    Applies to both floating point and integer numbers.
        ///    Only used if width &amp;gt; -1.
        /// </param>
        /// <param name="fill">
        ///    The value to pad if width &amp;gt; -1.  If empty, pads with spaces.
        ///    Another typical value is '0'.  String cannot be longer than 1 character.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    types and boolean.
        /// </remarks>
        public static Tensor as_string (Tensor input, int? precision = null, bool? scientific = null, bool? shortest = null, int? width = null, string fill = null, string name = "AsString")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (precision.HasValue)
                dict["precision"] = precision.Value;
            if (scientific.HasValue)
                dict["scientific"] = scientific.Value;
            if (shortest.HasValue)
                dict["shortest"] = shortest.Value;
            if (width.HasValue)
                dict["width"] = width.Value;
            if (fill != null)
                dict["fill"] = fill;
            var op = _op_def_lib._apply_op_helper("AsString", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes asin of x element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Asin'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor asin (Tensor x, string name = "Asin")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Asin", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes inverse hyperbolic sine of x element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Asinh'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor asinh (Tensor x, string name = "Asinh")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Asinh", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Asserts that the given condition is true.
        /// </summary>
        /// <param name="condition">
        ///    The condition to evaluate.
        /// </param>
        /// <param name="data">
        ///    The tensors to print out when condition is false.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Assert'.
        /// </param>
        /// <param name="summarize">
        ///    Print this many entries of each tensor.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    If <c>condition</c> evaluates to false, print the list of tensors in <c>data</c>.
        ///    <c>summarize</c> determines how many entries of the tensors to print.
        /// </remarks>
        public static Operation assert (Tensor condition, Tensor[] data, int? summarize = null, string name = "Assert")
        {
            var dict = new Dictionary<string, object>();
            dict["condition"] = condition;
            dict["data"] = data;
            if (summarize.HasValue)
                dict["summarize"] = summarize.Value;
            var op = _op_def_lib._apply_op_helper("Assert", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update 'ref' by assigning 'value' to it.
        /// </summary>
        /// <param name="referecne">
        ///    Should be from a <c>Variable</c> node. May be uninitialized.
        /// </param>
        /// <param name="value">
        ///    The value to be assigned to the variable.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Assign'.
        /// </param>
        /// <param name="validate_shape">
        ///    If true, the operation will validate that the shape
        ///    of 'value' matches the shape of the Tensor being assigned to.  If false,
        ///    'ref' will take on the shape of 'value'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, the assignment will be protected by a lock;
        ///    otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    = Same as "ref".  Returned as a convenience for operations that want
        ///    to use the new value after the variable has been reset.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation outputs "ref" after the assignment is done.
        ///    This makes it easier to chain operations that need to use the reset value.
        /// </remarks>
        public static Tensor assign (Tensor referecne, Tensor value, bool? validate_shape = null, bool? use_locking = null, string name = "Assign")
        {
            var dict = new Dictionary<string, object>();
            dict["ref"] = referecne;
            dict["value"] = value;
            if (validate_shape.HasValue)
                dict["validate_shape"] = validate_shape.Value;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("Assign", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update 'ref' by adding 'value' to it.
        /// </summary>
        /// <param name="referecne">
        ///    Should be from a <c>Variable</c> node.
        /// </param>
        /// <param name="value">
        ///    The value to be added to the variable.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AssignAdd'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, the addition will be protected by a lock;
        ///    otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    = Same as "ref".  Returned as a convenience for operations that want
        ///    to use the new value after the variable has been updated.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation outputs "ref" after the update is done.
        ///    This makes it easier to chain operations that need to use the reset value.
        /// </remarks>
        public static Tensor assign_add (Tensor referecne, Tensor value, bool? use_locking = null, string name = "AssignAdd")
        {
            var dict = new Dictionary<string, object>();
            dict["ref"] = referecne;
            dict["value"] = value;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("AssignAdd", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Adds a value to the current value of a variable.
        /// </summary>
        /// <param name="resource">
        ///    handle to the resource in which to store the variable.
        /// </param>
        /// <param name="value">
        ///    the value by which the variable will be incremented.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AssignAddVariableOp'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    Any ReadVariableOp with a control dependency on this op is guaranteed to
        ///    see the incremented value or a subsequent newer one.
        /// </remarks>
        public static Operation assign_add_variable_op (Tensor resource, Tensor value, string name = "AssignAddVariableOp")
        {
            var dict = new Dictionary<string, object>();
            dict["resource"] = resource;
            dict["value"] = value;
            var op = _op_def_lib._apply_op_helper("AssignAddVariableOp", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update 'ref' by subtracting 'value' from it.
        /// </summary>
        /// <param name="referecne">
        ///    Should be from a <c>Variable</c> node.
        /// </param>
        /// <param name="value">
        ///    The value to be subtracted to the variable.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AssignSub'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, the subtraction will be protected by a lock;
        ///    otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    = Same as "ref".  Returned as a convenience for operations that want
        ///    to use the new value after the variable has been updated.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation outputs "ref" after the update is done.
        ///    This makes it easier to chain operations that need to use the reset value.
        /// </remarks>
        public static Tensor assign_sub (Tensor referecne, Tensor value, bool? use_locking = null, string name = "AssignSub")
        {
            var dict = new Dictionary<string, object>();
            dict["ref"] = referecne;
            dict["value"] = value;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("AssignSub", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Subtracts a value from the current value of a variable.
        /// </summary>
        /// <param name="resource">
        ///    handle to the resource in which to store the variable.
        /// </param>
        /// <param name="value">
        ///    the value by which the variable will be incremented.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AssignSubVariableOp'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    Any ReadVariableOp with a control dependency on this op is guaranteed to
        ///    see the decremented value or a subsequent newer one.
        /// </remarks>
        public static Operation assign_sub_variable_op (Tensor resource, Tensor value, string name = "AssignSubVariableOp")
        {
            var dict = new Dictionary<string, object>();
            dict["resource"] = resource;
            dict["value"] = value;
            var op = _op_def_lib._apply_op_helper("AssignSubVariableOp", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Assigns a new value to a variable.
        /// </summary>
        /// <param name="resource">
        ///    handle to the resource in which to store the variable.
        /// </param>
        /// <param name="value">
        ///    the value to set the new tensor to use.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AssignVariableOp'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    Any ReadVariableOp with a control dependency on this op is guaranteed to return
        ///    this value or a subsequent newer value of the variable.
        /// </remarks>
        public static Operation assign_variable_op (Tensor resource, Tensor value, string name = "AssignVariableOp")
        {
            var dict = new Dictionary<string, object>();
            dict["resource"] = resource;
            dict["value"] = value;
            var op = _op_def_lib._apply_op_helper("AssignVariableOp", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Computes atan of x element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Atan'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor atan (Tensor x, string name = "Atan")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Atan", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes arctangent of <c>y/x</c> element-wise, respecting signs of the arguments.
        /// </summary>
        /// <param name="y">
        /// </param>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Atan2'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This is the angle \( \theta \in [-\pi, \pi] \) such that
        ///    \[ x = r \cos(\theta) \]
        ///    and
        ///    \[ y = r \sin(\theta) \]
        ///    where \(r = \sqrt(x^2 + y^2) \).
        /// </remarks>
        public static Tensor atan2 (Tensor y, Tensor x, string name = "Atan2")
        {
            var dict = new Dictionary<string, object>();
            dict["y"] = y;
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Atan2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes inverse hyperbolic tangent of x element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Atanh'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor atanh (Tensor x, string name = "Atanh")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Atanh", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Produces a visualization of audio data over time.
        /// </summary>
        /// <param name="input">
        ///    Float representation of audio data.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AudioSpectrogram'.
        /// </param>
        /// <param name="window_size">
        ///    Optional argument
        ///    How wide the input window is in samples. For the highest efficiency
        ///    this should be a power of two, but other values are accepted.
        /// </param>
        /// <param name="stride">
        ///    Optional argument
        ///    How widely apart the center of adjacent sample windows should be.
        /// </param>
        /// <param name="magnitude_squared">
        ///    Whether to return the squared magnitude or just the
        ///    magnitude. Using squared magnitude can avoid extra calculations.
        /// </param>
        /// <returns>
        ///    3D representation of the audio frequencies as an image.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Spectrograms are a standard way of representing audio information as a series of
        ///    slices of frequency information, one slice for each window of time. By joining
        ///    these together into a sequence, they form a distinctive fingerprint of the sound
        ///    over time.
        ///    
        ///    This op expects to receive audio data as an input, stored as floats in the range
        ///    -1 to 1, together with a window width in samples, and a stride specifying how
        ///    far to move the window between slices. From this it generates a three
        ///    dimensional output. The lowest dimension has an amplitude value for each
        ///    frequency during that time slice. The next dimension is time, with successive
        ///    frequency slices. The final dimension is for the channels in the input, so a
        ///    stereo audio input would have two here for example.
        ///    
        ///    This means the layout when converted and saved as an image is rotated 90 degrees
        ///    clockwise from a typical spectrogram. Time is descending down the Y axis, and
        ///    the frequency decreases from left to right.
        ///    
        ///    Each value in the result represents the square root of the sum of the real and
        ///    imaginary parts of an FFT on the current window of samples. In this way, the
        ///    lowest dimension represents the power of each frequency in the current window,
        ///    and adjacent windows are concatenated in the next dimension.
        ///    
        ///    To get a more intuitive and visual look at what this operation does, you can run
        ///    tensorflow/examples/wav_to_spectrogram to read in an audio file and save out the
        ///    resulting spectrogram as a PNG image.
        /// </remarks>
        public static Tensor audio_spectrogram (Tensor input, int window_size, int stride, bool? magnitude_squared = null, string name = "AudioSpectrogram")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["window_size"] = window_size;
            dict["stride"] = stride;
            if (magnitude_squared.HasValue)
                dict["magnitude_squared"] = magnitude_squared.Value;
            var op = _op_def_lib._apply_op_helper("AudioSpectrogram", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Outputs a <c>Summary</c> protocol buffer with audio.
        /// </summary>
        /// <param name="tag">
        ///    Scalar. Used to build the <c>tag</c> attribute of the summary values.
        /// </param>
        /// <param name="tensor">
        ///    2-D of shape <c>[batch_size, frames]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AudioSummary'.
        /// </param>
        /// <param name="sample_rate">
        ///    Optional argument
        ///    The sample rate of the signal in hertz.
        /// </param>
        /// <param name="max_outputs">
        ///    Max number of batch elements to generate audio for.
        /// </param>
        /// <returns>
        ///    Scalar. Serialized <c>Summary</c> protocol buffer.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The summary has up to <c>max_outputs</c> summary values containing audio. The
        ///    audio is built from <c>tensor</c> which must be 3-D with shape <c>[batch_size,
        ///    frames, channels]</c> or 2-D with shape <c>[batch_size, frames]</c>. The values are
        ///    assumed to be in the range of <c>[-1.0, 1.0]</c> with a sample rate of <c>sample_rate</c>.
        ///    
        ///    The <c>tag</c> argument is a scalar <c>Tensor</c> of type <c>string</c>.  It is used to
        ///    build the <c>tag</c> of the summary values:
        ///    
        ///    *  If <c>max_outputs</c> is 1, the summary value tag is '*tag*/audio'.
        ///    *  If <c>max_outputs</c> is greater than 1, the summary value tags are
        ///    generated sequentially as '*tag*/audio/0', '*tag*/audio/1', etc.
        /// </remarks>
        public static Tensor audio_summary (Tensor tag, Tensor tensor, float sample_rate, int? max_outputs = null, string name = "AudioSummary")
        {
            var dict = new Dictionary<string, object>();
            dict["tag"] = tag;
            dict["tensor"] = tensor;
            dict["sample_rate"] = sample_rate;
            if (max_outputs.HasValue)
                dict["max_outputs"] = max_outputs.Value;
            var op = _op_def_lib._apply_op_helper("AudioSummary", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Outputs a <c>Summary</c> protocol buffer with audio.
        /// </summary>
        /// <param name="tag">
        ///    Scalar. Used to build the <c>tag</c> attribute of the summary values.
        /// </param>
        /// <param name="tensor">
        ///    2-D of shape <c>[batch_size, frames]</c>.
        /// </param>
        /// <param name="sample_rate">
        ///    The sample rate of the signal in hertz.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AudioSummaryV2'.
        /// </param>
        /// <param name="max_outputs">
        ///    Max number of batch elements to generate audio for.
        /// </param>
        /// <returns>
        ///    Scalar. Serialized <c>Summary</c> protocol buffer.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The summary has up to <c>max_outputs</c> summary values containing audio. The
        ///    audio is built from <c>tensor</c> which must be 3-D with shape <c>[batch_size,
        ///    frames, channels]</c> or 2-D with shape <c>[batch_size, frames]</c>. The values are
        ///    assumed to be in the range of <c>[-1.0, 1.0]</c> with a sample rate of <c>sample_rate</c>.
        ///    
        ///    The <c>tag</c> argument is a scalar <c>Tensor</c> of type <c>string</c>.  It is used to
        ///    build the <c>tag</c> of the summary values:
        ///    
        ///    *  If <c>max_outputs</c> is 1, the summary value tag is '*tag*/audio'.
        ///    *  If <c>max_outputs</c> is greater than 1, the summary value tags are
        ///    generated sequentially as '*tag*/audio/0', '*tag*/audio/1', etc.
        /// </remarks>
        public static Tensor audio_summary_v2 (Tensor tag, Tensor tensor, Tensor sample_rate, int? max_outputs = null, string name = "AudioSummaryV2")
        {
            var dict = new Dictionary<string, object>();
            dict["tag"] = tag;
            dict["tensor"] = tensor;
            dict["sample_rate"] = sample_rate;
            if (max_outputs.HasValue)
                dict["max_outputs"] = max_outputs.Value;
            var op = _op_def_lib._apply_op_helper("AudioSummaryV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Performs average pooling on the input.
        /// </summary>
        /// <param name="value">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AvgPool'.
        /// </param>
        /// <param name="ksize">
        ///    Optional argument
        ///    The size of the sliding window for each dimension of <c>value</c>.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    The stride of the sliding window for each dimension of <c>value</c>.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="data_format">
        ///    Specify the data format of the input and output data. With the
        ///    default format "NHWC", the data is stored in the order of:
        ///    [batch, in_height, in_width, in_channels].
        ///    Alternatively, the format could be "NCHW", the data storage order of:
        ///    [batch, in_channels, in_height, in_width].
        /// </param>
        /// <returns>
        ///    The average pooled output tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Each entry in <c>output</c> is the mean of the corresponding size <c>ksize</c>
        ///    window in <c>value</c>.
        /// </remarks>
        public static Tensor avg_pool (Tensor value, int[] ksize, int[] strides, string padding, string data_format = null, string name = "AvgPool")
        {
            var dict = new Dictionary<string, object>();
            dict["value"] = value;
            dict["ksize"] = ksize;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (data_format != null)
                dict["data_format"] = data_format;
            var op = _op_def_lib._apply_op_helper("AvgPool", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Performs 3D average pooling on the input.
        /// </summary>
        /// <param name="input">
        ///    Shape <c>[batch, depth, rows, cols, channels]</c> tensor to pool over.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AvgPool3D'.
        /// </param>
        /// <param name="ksize">
        ///    Optional argument
        ///    1-D tensor of length 5. The size of the window for each dimension of
        ///    the input tensor. Must have <c>ksize[0] = ksize[4] = 1</c>.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    1-D tensor of length 5. The stride of the sliding window for each
        ///    dimension of <c>input</c>. Must have <c>strides[0] = strides[4] = 1</c>.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="data_format">
        ///    The data format of the input and output data. With the
        ///    default format "NDHWC", the data is stored in the order of:
        ///    [batch, in_depth, in_height, in_width, in_channels].
        ///    Alternatively, the format could be "NCDHW", the data storage order is:
        ///    [batch, in_channels, in_depth, in_height, in_width].
        /// </param>
        /// <returns>
        ///    The average pooled output tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor avg_pool3d (Tensor input, int[] ksize, int[] strides, string padding, string data_format = null, string name = "AvgPool3D")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["ksize"] = ksize;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (data_format != null)
                dict["data_format"] = data_format;
            var op = _op_def_lib._apply_op_helper("AvgPool3D", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes gradients of average pooling function.
        /// </summary>
        /// <param name="orig_input_shape">
        ///    The original input dimensions.
        /// </param>
        /// <param name="grad">
        ///    Output backprop of shape <c>[batch, depth, rows, cols, channels]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AvgPool3DGrad'.
        /// </param>
        /// <param name="ksize">
        ///    Optional argument
        ///    1-D tensor of length 5. The size of the window for each dimension of
        ///    the input tensor. Must have <c>ksize[0] = ksize[4] = 1</c>.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    1-D tensor of length 5. The stride of the sliding window for each
        ///    dimension of <c>input</c>. Must have <c>strides[0] = strides[4] = 1</c>.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="data_format">
        ///    The data format of the input and output data. With the
        ///    default format "NDHWC", the data is stored in the order of:
        ///    [batch, in_depth, in_height, in_width, in_channels].
        ///    Alternatively, the format could be "NCDHW", the data storage order is:
        ///    [batch, in_channels, in_depth, in_height, in_width].
        /// </param>
        /// <returns>
        ///    The backprop for input.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor avg_pool3d_grad (Tensor orig_input_shape, Tensor grad, int[] ksize, int[] strides, string padding, string data_format = null, string name = "AvgPool3DGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["orig_input_shape"] = orig_input_shape;
            dict["grad"] = grad;
            dict["ksize"] = ksize;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (data_format != null)
                dict["data_format"] = data_format;
            var op = _op_def_lib._apply_op_helper("AvgPool3DGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes gradients of the average pooling function.
        /// </summary>
        /// <param name="orig_input_shape">
        ///    1-D.  Shape of the original input to <c>avg_pool</c>.
        /// </param>
        /// <param name="grad">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.  Gradients w.r.t.
        ///    the output of <c>avg_pool</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'AvgPoolGrad'.
        /// </param>
        /// <param name="ksize">
        ///    Optional argument
        ///    The size of the sliding window for each dimension of the input.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    The stride of the sliding window for each dimension of the input.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="data_format">
        ///    Specify the data format of the input and output data. With the
        ///    default format "NHWC", the data is stored in the order of:
        ///    [batch, in_height, in_width, in_channels].
        ///    Alternatively, the format could be "NCHW", the data storage order of:
        ///    [batch, in_channels, in_height, in_width].
        /// </param>
        /// <returns>
        ///    4-D.  Gradients w.r.t. the input of <c>avg_pool</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor avg_pool_grad (Tensor orig_input_shape, Tensor grad, int[] ksize, int[] strides, string padding, string data_format = null, string name = "AvgPoolGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["orig_input_shape"] = orig_input_shape;
            dict["grad"] = grad;
            dict["ksize"] = ksize;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (data_format != null)
                dict["data_format"] = data_format;
            var op = _op_def_lib._apply_op_helper("AvgPoolGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Defines a barrier that persists across different graph executions.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Barrier'.
        /// </param>
        /// <param name="component_types">
        ///    Optional argument
        ///    The type of each component in a value.
        /// </param>
        /// <param name="shapes">
        ///    The shape of each component in a value. Each shape must be 1 in the
        ///    first dimension. The length of this attr must be the same as the length of
        ///    component_types.
        /// </param>
        /// <param name="capacity">
        ///    The capacity of the barrier.  The default capacity is MAX_INT32,
        ///    which is the largest capacity of the underlying queue.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this barrier is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this barrier will be shared under the given name
        ///    across multiple sessions.
        /// </param>
        /// <returns>
        ///    The handle to the barrier.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    A barrier represents a key-value map, where each key is a string, and
        ///    each value is a tuple of tensors.
        ///    
        ///    At runtime, the barrier contains 'complete' and 'incomplete'
        ///    elements. A complete element has defined tensors for all components of
        ///    its value tuple, and may be accessed using BarrierTakeMany. An
        ///    incomplete element has some undefined components in its value tuple,
        ///    and may be updated using BarrierInsertMany.
        /// </remarks>
        public static Tensor barrier (TF_DataType[] component_types, TensorShape[] shapes = null, int? capacity = null, string container = null, string shared_name = null, string name = "Barrier")
        {
            var dict = new Dictionary<string, object>();
            dict["component_types"] = component_types;
            if (shapes != null)
                dict["shapes"] = shapes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("Barrier", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Closes the given barrier.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a barrier.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BarrierClose'.
        /// </param>
        /// <param name="cancel_pending_enqueues">
        ///    If true, all pending enqueue requests that are
        ///    blocked on the barrier's queue will be canceled. InsertMany will fail, even
        ///    if no new key is introduced.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    This operation signals that no more new elements will be inserted in the
        ///    given barrier. Subsequent InsertMany that try to introduce a new key will fail.
        ///    Subsequent InsertMany operations that just add missing components to already
        ///    existing elements will continue to succeed. Subsequent TakeMany operations will
        ///    continue to succeed if sufficient completed elements remain in the barrier.
        ///    Subsequent TakeMany operations that would block will fail immediately.
        /// </remarks>
        public static Operation barrier_close (Tensor handle, bool? cancel_pending_enqueues = null, string name = "BarrierClose")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            if (cancel_pending_enqueues.HasValue)
                dict["cancel_pending_enqueues"] = cancel_pending_enqueues.Value;
            var op = _op_def_lib._apply_op_helper("BarrierClose", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Computes the number of incomplete elements in the given barrier.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a barrier.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BarrierIncompleteSize'.
        /// </param>
        /// <returns>
        ///    The number of incomplete elements (i.e. those with some of their value
        ///    components not set) in the barrier.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor barrier_incomplete_size (Tensor handle, string name = "BarrierIncompleteSize")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            var op = _op_def_lib._apply_op_helper("BarrierIncompleteSize", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    For each key, assigns the respective value to the specified component.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a barrier.
        /// </param>
        /// <param name="keys">
        ///    A one-dimensional tensor of keys, with length n.
        /// </param>
        /// <param name="values">
        ///    An any-dimensional tensor of values, which are associated with the
        ///    respective keys. The 0th dimension must have length n.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BarrierInsertMany'.
        /// </param>
        /// <param name="component_index">
        ///    Optional argument
        ///    The component of the barrier elements that is being assigned.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    If a key is not found in the barrier, this operation will create a new
        ///    incomplete element. If a key is found in the barrier, and the element
        ///    already has a value at component_index, this operation will fail with
        ///    INVALID_ARGUMENT, and leave the barrier in an undefined state.
        /// </remarks>
        public static Operation barrier_insert_many (Tensor handle, Tensor keys, Tensor values, int component_index, string name = "BarrierInsertMany")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["keys"] = keys;
            dict["values"] = values;
            dict["component_index"] = component_index;
            var op = _op_def_lib._apply_op_helper("BarrierInsertMany", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Computes the number of complete elements in the given barrier.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a barrier.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BarrierReadySize'.
        /// </param>
        /// <returns>
        ///    The number of complete elements (i.e. those with all of their value
        ///    components set) in the barrier.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor barrier_ready_size (Tensor handle, string name = "BarrierReadySize")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            var op = _op_def_lib._apply_op_helper("BarrierReadySize", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Takes the given number of completed elements from a barrier.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a barrier.
        /// </param>
        /// <param name="num_elements">
        ///    A single-element tensor containing the number of elements to
        ///    take.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BarrierTakeMany'.
        /// </param>
        /// <param name="component_types">
        ///    Optional argument
        ///    The type of each component in a value.
        /// </param>
        /// <param name="allow_small_batch">
        ///    Allow to return less than num_elements items if barrier is
        ///    already closed.
        /// </param>
        /// <param name="wait_for_incomplete">
        /// </param>
        /// <param name="timeout_ms">
        ///    If the queue is empty, this operation will block for up to
        ///    timeout_ms milliseconds.
        ///    Note: This option is not supported yet.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    indices : A one-dimensional tensor of indices, with length num_elems.
        ///    These indices refer to the batch in which the values were placed into the
        ///    barrier (starting with MIN_LONG and increasing with each BarrierInsertMany).
        ///    keys : A one-dimensional tensor of keys, with length num_elements.
        ///    values : One any-dimensional tensor per component in a barrier element. All
        ///    values have length num_elements in the 0th dimension.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    This operation concatenates completed-element component tensors along
        ///    the 0th dimension to make a single component tensor.
        ///    
        ///    Elements come out of the barrier when they are complete, and in the order
        ///    in which they were placed into the barrier.  The indices output provides
        ///    information about the batch in which each element was originally inserted
        ///    into the barrier.
        /// </remarks>
        public static (Tensor indices, Tensor keys, Tensor[] values) barrier_take_many (Tensor handle, Tensor num_elements, TF_DataType[] component_types, bool? allow_small_batch = null, bool? wait_for_incomplete = null, int? timeout_ms = null, string name = "BarrierTakeMany")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["num_elements"] = num_elements;
            dict["component_types"] = component_types;
            if (allow_small_batch.HasValue)
                dict["allow_small_batch"] = allow_small_batch.Value;
            if (wait_for_incomplete.HasValue)
                dict["wait_for_incomplete"] = wait_for_incomplete.Value;
            if (timeout_ms.HasValue)
                dict["timeout_ms"] = timeout_ms.Value;
            var op = _op_def_lib._apply_op_helper("BarrierTakeMany", name: name, keywords: dict);
            int _idx = 0;
            var indices = op.outputs[_idx++];
            var keys = op.outputs[_idx++];
            var values = Enumerable.Range(0, op.OutputListLength("values")).Select(_ => op.outputs[_idx++]).ToArray();
            return (indices, keys, values);
        }

        /// <summary>
        ///    Batches all input tensors nondeterministically.
        /// </summary>
        /// <param name="in_tensors">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Batch'.
        /// </param>
        /// <param name="num_batch_threads">
        ///    Optional argument
        /// </param>
        /// <param name="max_batch_size">
        ///    Optional argument
        /// </param>
        /// <param name="batch_timeout_micros">
        ///    Optional argument
        /// </param>
        /// <param name="grad_timeout_micros">
        ///    Optional argument
        /// </param>
        /// <param name="max_enqueued_batches">
        /// </param>
        /// <param name="allowed_batch_sizes">
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <param name="batching_queue">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    batched_tensors :
        ///    batch_index :
        ///    id :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    When many instances of this Op are being run concurrently with the same
        ///    container/shared_name in the same device, some will output zero-shaped Tensors
        ///    and others will output Tensors of size up to max_batch_size.
        ///    
        ///    All Tensors in in_tensors are batched together (so, for example, labels and
        ///    features should be batched with a single instance of this operation.
        ///    
        ///    Each invocation of batch emits an <c>id</c> scalar which will be used to identify
        ///    this particular invocation when doing unbatch or its gradient.
        ///    
        ///    Each op which emits a non-empty batch will also emit a non-empty batch_index
        ///    Tensor, which, is a [K, 3] matrix where each row contains the invocation's id,
        ///    start, and length of elements of each set of Tensors present in batched_tensors.
        ///    
        ///    Batched tensors are concatenated along the first dimension, and all tensors in
        ///    in_tensors must have the first dimension of the same size.
        ///    
        ///    in_tensors: The tensors to be batched.
        ///    num_batch_threads: Number of scheduling threads for processing batches of work.
        ///    Determines the number of batches processed in parallel.
        ///    max_batch_size: Batch sizes will never be bigger than this.
        ///    batch_timeout_micros: Maximum number of microseconds to wait before outputting
        ///    an incomplete batch.
        ///    allowed_batch_sizes: Optional list of allowed batch sizes. If left empty, does
        ///    nothing. Otherwise, supplies a list of batch sizes, causing the op to pad
        ///    batches up to one of those sizes. The entries must increase monotonically, and
        ///    the final entry must equal max_batch_size.
        ///    grad_timeout_micros: The timeout to use for the gradient. See Unbatch.
        ///    batched_tensors: Either empty tensors or a batch of concatenated Tensors.
        ///    batch_index: If out_tensors is non-empty, has information to invert it.
        ///    container: Controls the scope of sharing of this batch.
        ///    id: always contains a scalar with a unique ID for this invocation of Batch.
        ///    shared_name: Concurrently running instances of batch in the same device with the
        ///    same container and shared_name will batch their elements together. If left
        ///    empty, the op name will be used as the shared name.
        ///    T: the types of tensors to be batched.
        /// </remarks>
        public static (Tensor[] batched_tensors, Tensor batch_index, Tensor id) batch (Tensor[] in_tensors, int num_batch_threads, int max_batch_size, int batch_timeout_micros, int grad_timeout_micros, int? max_enqueued_batches = null, int[] allowed_batch_sizes = null, string container = null, string shared_name = null, string batching_queue = null, string name = "Batch")
        {
            var dict = new Dictionary<string, object>();
            dict["in_tensors"] = in_tensors;
            dict["num_batch_threads"] = num_batch_threads;
            dict["max_batch_size"] = max_batch_size;
            dict["batch_timeout_micros"] = batch_timeout_micros;
            dict["grad_timeout_micros"] = grad_timeout_micros;
            if (max_enqueued_batches.HasValue)
                dict["max_enqueued_batches"] = max_enqueued_batches.Value;
            if (allowed_batch_sizes != null)
                dict["allowed_batch_sizes"] = allowed_batch_sizes;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            if (batching_queue != null)
                dict["batching_queue"] = batching_queue;
            var op = _op_def_lib._apply_op_helper("Batch", name: name, keywords: dict);
            int _idx = 0;
            var batched_tensors = Enumerable.Range(0, op.OutputListLength("batched_tensors")).Select(_ => op.outputs[_idx++]).ToArray();
            var batch_index = op.outputs[_idx++];
            var id = op.outputs[_idx++];
            return (batched_tensors, batch_index, id);
        }

        /// <summary>
        ///    Creates a dataset that batches <c>batch_size</c> elements from <c>input_dataset</c>.
        /// </summary>
        /// <param name="input_dataset">
        /// </param>
        /// <param name="batch_size">
        ///    A scalar representing the number of elements to accumulate in a
        ///    batch.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BatchDataset'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor batch_dataset (Tensor input_dataset, Tensor batch_size, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "BatchDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["batch_size"] = batch_size;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("BatchDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a dataset that batches <c>batch_size</c> elements from <c>input_dataset</c>.
        /// </summary>
        /// <param name="input_dataset">
        /// </param>
        /// <param name="batch_size">
        ///    A scalar representing the number of elements to accumulate in a batch.
        /// </param>
        /// <param name="drop_remainder">
        ///    A scalar representing whether the last batch should be dropped in case its size
        ///    is smaller than desired.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BatchDatasetV2'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor batch_dataset_v2 (Tensor input_dataset, Tensor batch_size, Tensor drop_remainder, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "BatchDatasetV2")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["batch_size"] = batch_size;
            dict["drop_remainder"] = drop_remainder;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("BatchDatasetV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Multiplies slices of two tensors in batches.
        /// </summary>
        /// <param name="x">
        ///    2-D or higher with shape <c>[..., r_x, c_x]</c>.
        /// </param>
        /// <param name="y">
        ///    2-D or higher with shape <c>[..., r_y, c_y]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BatchMatMul'.
        /// </param>
        /// <param name="adj_x">
        ///    If <c>True</c>, adjoint the slices of <c>x</c>. Defaults to <c>False</c>.
        /// </param>
        /// <param name="adj_y">
        ///    If <c>True</c>, adjoint the slices of <c>y</c>. Defaults to <c>False</c>.
        /// </param>
        /// <returns>
        ///    3-D or higher with shape <c>[..., r_o, c_o]</c>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Multiplies all slices of <c>Tensor</c> <c>x</c> and <c>y</c> (each slice can be
        ///    viewed as an element of a batch), and arranges the individual results
        ///    in a single output tensor of the same batch size. Each of the
        ///    individual slices can optionally be adjointed (to adjoint a matrix
        ///    means to transpose and conjugate it) before multiplication by setting
        ///    the <c>adj_x</c> or <c>adj_y</c> flag to <c>True</c>, which are by default <c>False</c>.
        ///    
        ///    The input tensors <c>x</c> and <c>y</c> are 2-D or higher with shape <c>[..., r_x, c_x]</c>
        ///    and <c>[..., r_y, c_y]</c>.
        ///    
        ///    The output tensor is 2-D or higher with shape <c>[..., r_o, c_o]</c>, where:
        ///    
        ///    r_o = c_x if adj_x else r_x
        ///    c_o = r_y if adj_y else c_y
        ///    
        ///    It is computed as:
        ///    
        ///    output[..., :, :] = matrix(x[..., :, :]) * matrix(y[..., :, :])
        /// </remarks>
        public static Tensor batch_mat_mul (Tensor x, Tensor y, bool? adj_x = null, bool? adj_y = null, string name = "BatchMatMul")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            if (adj_x.HasValue)
                dict["adj_x"] = adj_x.Value;
            if (adj_y.HasValue)
                dict["adj_y"] = adj_y.Value;
            var op = _op_def_lib._apply_op_helper("BatchMatMul", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Batch normalization.
        /// </summary>
        /// <param name="t">
        ///    A 4D input Tensor.
        /// </param>
        /// <param name="m">
        ///    A 1D mean Tensor with size matching the last dimension of t.
        ///    This is the first output from tf.nn.moments,
        ///    or a saved moving average thereof.
        /// </param>
        /// <param name="v">
        ///    A 1D variance Tensor with size matching the last dimension of t.
        ///    This is the second output from tf.nn.moments,
        ///    or a saved moving average thereof.
        /// </param>
        /// <param name="beta">
        ///    A 1D beta Tensor with size matching the last dimension of t.
        ///    An offset to be added to the normalized tensor.
        /// </param>
        /// <param name="gamma">
        ///    A 1D gamma Tensor with size matching the last dimension of t.
        ///    If "scale_after_normalization" is true, this tensor will be multiplied
        ///    with the normalized tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BatchNormWithGlobalNormalization'.
        /// </param>
        /// <param name="variance_epsilon">
        ///    Optional argument
        ///    A small float number to avoid dividing by 0.
        /// </param>
        /// <param name="scale_after_normalization">
        ///    Optional argument
        ///    A bool indicating whether the resulted tensor
        ///    needs to be multiplied with gamma.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op is deprecated. Prefer <c>tf.nn.batch_normalization</c>.
        /// </remarks>
        public static Tensor batch_norm_with_global_normalization (Tensor t, Tensor m, Tensor v, Tensor beta, Tensor gamma, float variance_epsilon, bool scale_after_normalization, string name = "BatchNormWithGlobalNormalization")
        {
            var dict = new Dictionary<string, object>();
            dict["t"] = t;
            dict["m"] = m;
            dict["v"] = v;
            dict["beta"] = beta;
            dict["gamma"] = gamma;
            dict["variance_epsilon"] = variance_epsilon;
            dict["scale_after_normalization"] = scale_after_normalization;
            var op = _op_def_lib._apply_op_helper("BatchNormWithGlobalNormalization", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Gradients for batch normalization.
        /// </summary>
        /// <param name="t">
        ///    A 4D input Tensor.
        /// </param>
        /// <param name="m">
        ///    A 1D mean Tensor with size matching the last dimension of t.
        ///    This is the first output from tf.nn.moments,
        ///    or a saved moving average thereof.
        /// </param>
        /// <param name="v">
        ///    A 1D variance Tensor with size matching the last dimension of t.
        ///    This is the second output from tf.nn.moments,
        ///    or a saved moving average thereof.
        /// </param>
        /// <param name="gamma">
        ///    A 1D gamma Tensor with size matching the last dimension of t.
        ///    If "scale_after_normalization" is true, this Tensor will be multiplied
        ///    with the normalized Tensor.
        /// </param>
        /// <param name="backprop">
        ///    4D backprop Tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BatchNormWithGlobalNormalizationGrad'.
        /// </param>
        /// <param name="variance_epsilon">
        ///    Optional argument
        ///    A small float number to avoid dividing by 0.
        /// </param>
        /// <param name="scale_after_normalization">
        ///    Optional argument
        ///    A bool indicating whether the resulted tensor
        ///    needs to be multiplied with gamma.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    dx : 4D backprop tensor for input.
        ///    dm : 1D backprop tensor for mean.
        ///    dv : 1D backprop tensor for variance.
        ///    db : 1D backprop tensor for beta.
        ///    dg : 1D backprop tensor for gamma.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    This op is deprecated. See <c>tf.nn.batch_normalization</c>.
        /// </remarks>
        public static (Tensor dx, Tensor dm, Tensor dv, Tensor db, Tensor dg) batch_norm_with_global_normalization_grad (Tensor t, Tensor m, Tensor v, Tensor gamma, Tensor backprop, float variance_epsilon, bool scale_after_normalization, string name = "BatchNormWithGlobalNormalizationGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["t"] = t;
            dict["m"] = m;
            dict["v"] = v;
            dict["gamma"] = gamma;
            dict["backprop"] = backprop;
            dict["variance_epsilon"] = variance_epsilon;
            dict["scale_after_normalization"] = scale_after_normalization;
            var op = _op_def_lib._apply_op_helper("BatchNormWithGlobalNormalizationGrad", name: name, keywords: dict);
            int _idx = 0;
            var dx = op.outputs[_idx++];
            var dm = op.outputs[_idx++];
            var dv = op.outputs[_idx++];
            var db = op.outputs[_idx++];
            var dg = op.outputs[_idx++];
            return (dx, dm, dv, db, dg);
        }

        /// <summary>
        ///    BatchToSpace for 4-D tensors of type T.
        /// </summary>
        /// <param name="input">
        ///    4-D tensor with shape
        ///    <c>[batch*block_size*block_size, height_pad/block_size, width_pad/block_size,
        ///    depth]</c>. Note that the batch size of the input tensor must be divisible by
        ///    <c>block_size * block_size</c>.
        /// </param>
        /// <param name="crops">
        ///    2-D tensor of non-negative integers with shape <c>[2, 2]</c>. It specifies
        ///    how many elements to crop from the intermediate result across the spatial
        ///    dimensions as follows:
        ///    
        ///    crops = [[crop_top, crop_bottom], [crop_left, crop_right]]
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BatchToSpace'.
        /// </param>
        /// <param name="block_size">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    4-D with shape <c>[batch, height, width, depth]</c>, where:
        ///    
        ///    height = height_pad - crop_top - crop_bottom
        ///    width = width_pad - crop_left - crop_right
        ///    
        ///    The attr <c>block_size</c> must be greater than one. It indicates the block size.
        ///    
        ///    Some examples:
        ///    
        ///    (1) For the following input of shape <c>[4, 1, 1, 1]</c> and block_size of 2:
        ///    
        ///   <code>
        ///    [[[[1]]], [[[2]]], [[[3]]], [[[4]]]]
        ///   </code>
        ///    
        ///    The output tensor has shape <c>[1, 2, 2, 1]</c> and value:
        ///    
        ///   <code>
        ///    x = [[[[1], [2]], [[3], [4]]]]
        ///   </code>
        ///    
        ///    (2) For the following input of shape <c>[4, 1, 1, 3]</c> and block_size of 2:
        ///    
        ///   <code>
        ///    [[[1, 2, 3]], [[4, 5, 6]], [[7, 8, 9]], [[10, 11, 12]]]
        ///   </code>
        ///    
        ///    The output tensor has shape <c>[1, 2, 2, 3]</c> and value:
        ///    
        ///   <code>
        ///    x = [[[[1, 2, 3], [4, 5, 6]],
        ///    [[7, 8, 9], [10, 11, 12]]]]
        ///   </code>
        ///    
        ///    (3) For the following input of shape <c>[4, 2, 2, 1]</c> and block_size of 2:
        ///    
        ///   <code>
        ///    x = [[[[1], [3]], [[9], [11]]],
        ///    [[[2], [4]], [[10], [12]]],
        ///    [[[5], [7]], [[13], [15]]],
        ///    [[[6], [8]], [[14], [16]]]]
        ///   </code>
        ///    
        ///    The output tensor has shape <c>[1, 4, 4, 1]</c> and value:
        ///    
        ///   <code>
        ///    x = [[[1],   [2],  [3],  [4]],
        ///    [[5],   [6],  [7],  [8]],
        ///    [[9],  [10], [11],  [12]],
        ///    [[13], [14], [15],  [16]]]
        ///   </code>
        ///    
        ///    (4) For the following input of shape <c>[8, 1, 2, 1]</c> and block_size of 2:
        ///    
        ///   <code>
        ///    x = [[[[1], [3]]], [[[9], [11]]], [[[2], [4]]], [[[10], [12]]],
        ///    [[[5], [7]]], [[[13], [15]]], [[[6], [8]]], [[[14], [16]]]]
        ///   </code>
        ///    
        ///    The output tensor has shape <c>[2, 2, 4, 1]</c> and value:
        ///    
        ///   <code>
        ///    x = [[[[1], [3]], [[5], [7]]],
        ///    [[[2], [4]], [[10], [12]]],
        ///    [[[5], [7]], [[13], [15]]],
        ///    [[[6], [8]], [[14], [16]]]]
        ///   </code>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This is a legacy version of the more general BatchToSpaceND.
        ///    
        ///    Rearranges (permutes) data from batch into blocks of spatial data, followed by
        ///    cropping. This is the reverse transformation of SpaceToBatch. More specifically,
        ///    this op outputs a copy of the input tensor where values from the <c>batch</c>
        ///    dimension are moved in spatial blocks to the <c>height</c> and <c>width</c> dimensions,
        ///    followed by cropping along the <c>height</c> and <c>width</c> dimensions.
        /// </remarks>
        public static Tensor batch_to_space (Tensor input, Tensor crops, int block_size, string name = "BatchToSpace")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["crops"] = crops;
            dict["block_size"] = block_size;
            var op = _op_def_lib._apply_op_helper("BatchToSpace", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    BatchToSpace for N-D tensors of type T.
        /// </summary>
        /// <param name="input">
        ///    N-D with shape <c>input_shape = [batch] + spatial_shape + remaining_shape</c>,
        ///    where spatial_shape has M dimensions.
        /// </param>
        /// <param name="block_shape">
        ///    1-D with shape <c>[M]</c>, all values must be &amp;gt;= 1.
        /// </param>
        /// <param name="crops">
        ///    2-D with shape <c>[M, 2]</c>, all values must be &amp;gt;= 0.
        ///    <c>crops[i] = [crop_start, crop_end]</c> specifies the amount to crop from input
        ///    dimension <c>i + 1</c>, which corresponds to spatial dimension <c>i</c>.  It is
        ///    required that
        ///    <c>crop_start[i] + crop_end[i] &amp;lt;= block_shape[i] * input_shape[i + 1]</c>.
        ///    
        ///    This operation is equivalent to the following steps:
        ///    
        ///    1. Reshape <c>input</c> to <c>reshaped</c> of shape:
        ///    [block_shape[0], ..., block_shape[M-1],
        ///    batch / prod(block_shape),
        ///    input_shape[1], ..., input_shape[N-1]]
        ///    
        ///    2. Permute dimensions of <c>reshaped</c> to produce <c>permuted</c> of shape
        ///    [batch / prod(block_shape),
        ///    
        ///    input_shape[1], block_shape[0],
        ///    ...,
        ///    input_shape[M], block_shape[M-1],
        ///    
        ///    input_shape[M+1], ..., input_shape[N-1]]
        ///    
        ///    3. Reshape <c>permuted</c> to produce <c>reshaped_permuted</c> of shape
        ///    [batch / prod(block_shape),
        ///    
        ///    input_shape[1] * block_shape[0],
        ///    ...,
        ///    input_shape[M] * block_shape[M-1],
        ///    
        ///    input_shape[M+1],
        ///    ...,
        ///    input_shape[N-1]]
        ///    
        ///    4. Crop the start and end of dimensions <c>[1, ..., M]</c> of
        ///    <c>reshaped_permuted</c> according to <c>crops</c> to produce the output of shape:
        ///    [batch / prod(block_shape),
        ///    
        ///    input_shape[1] * block_shape[0] - crops[0,0] - crops[0,1],
        ///    ...,
        ///    input_shape[M] * block_shape[M-1] - crops[M-1,0] - crops[M-1,1],
        ///    
        ///    input_shape[M+1], ..., input_shape[N-1]]
        ///    
        ///    Some examples:
        ///    
        ///    (1) For the following input of shape <c>[4, 1, 1, 1]</c>, <c>block_shape = [2, 2]</c>, and
        ///    <c>crops = [[0, 0], [0, 0]]</c>:
        ///    
        ///   <code>
        ///    [[[[1]]], [[[2]]], [[[3]]], [[[4]]]]
        ///   </code>
        ///    
        ///    The output tensor has shape <c>[1, 2, 2, 1]</c> and value:
        ///    
        ///   <code>
        ///    x = [[[[1], [2]], [[3], [4]]]]
        ///   </code>
        ///    
        ///    (2) For the following input of shape <c>[4, 1, 1, 3]</c>, <c>block_shape = [2, 2]</c>, and
        ///    <c>crops = [[0, 0], [0, 0]]</c>:
        ///    
        ///   <code>
        ///    [[[1, 2, 3]], [[4, 5, 6]], [[7, 8, 9]], [[10, 11, 12]]]
        ///   </code>
        ///    
        ///    The output tensor has shape <c>[1, 2, 2, 3]</c> and value:
        ///    
        ///   <code>
        ///    x = [[[[1, 2, 3], [4, 5, 6]],
        ///    [[7, 8, 9], [10, 11, 12]]]]
        ///   </code>
        ///    
        ///    (3) For the following input of shape <c>[4, 2, 2, 1]</c>, <c>block_shape = [2, 2]</c>, and
        ///    <c>crops = [[0, 0], [0, 0]]</c>:
        ///    
        ///   <code>
        ///    x = [[[[1], [3]], [[9], [11]]],
        ///    [[[2], [4]], [[10], [12]]],
        ///    [[[5], [7]], [[13], [15]]],
        ///    [[[6], [8]], [[14], [16]]]]
        ///   </code>
        ///    
        ///    The output tensor has shape <c>[1, 4, 4, 1]</c> and value:
        ///    
        ///   <code>
        ///    x = [[[1],   [2],  [3],  [4]],
        ///    [[5],   [6],  [7],  [8]],
        ///    [[9],  [10], [11],  [12]],
        ///    [[13], [14], [15],  [16]]]
        ///   </code>
        ///    
        ///    (4) For the following input of shape <c>[8, 1, 3, 1]</c>, <c>block_shape = [2, 2]</c>, and
        ///    <c>crops = [[0, 0], [2, 0]]</c>:
        ///    
        ///   <code>
        ///    x = [[[[0], [1], [3]]], [[[0], [9], [11]]],
        ///    [[[0], [2], [4]]], [[[0], [10], [12]]],
        ///    [[[0], [5], [7]]], [[[0], [13], [15]]],
        ///    [[[0], [6], [8]]], [[[0], [14], [16]]]]
        ///   </code>
        ///    
        ///    The output tensor has shape <c>[2, 2, 4, 1]</c> and value:
        ///    
        ///   <code>
        ///    x = [[[[1],   [2],  [3],  [4]],
        ///    [[5],   [6],  [7],  [8]]],
        ///    [[[9],  [10], [11],  [12]],
        ///    [[13], [14], [15],  [16]]]]
        ///   </code>
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BatchToSpaceND'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation reshapes the "batch" dimension 0 into <c>M + 1</c> dimensions of shape
        ///    <c>block_shape + [batch]</c>, interleaves these blocks back into the grid defined by
        ///    the spatial dimensions <c>[1, ..., M]</c>, to obtain a result with the same rank as
        ///    the input.  The spatial dimensions of this intermediate result are then
        ///    optionally cropped according to <c>crops</c> to produce the output.  This is the
        ///    reverse of SpaceToBatch.  See below for a precise description.
        /// </remarks>
        public static Tensor batch_to_space_n_d (Tensor input, Tensor block_shape, Tensor crops, string name = "BatchToSpaceND")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["block_shape"] = block_shape;
            dict["crops"] = crops;
            var op = _op_def_lib._apply_op_helper("BatchToSpaceND", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the Bessel i0e function of <c>x</c> element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BesselI0e'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Exponentially scaled modified Bessel function of order 0 defined as
        ///    <c>bessel_i0e(x) = exp(-abs(x)) bessel_i0(x)</c>.
        ///    
        ///    This function is faster and numerically stabler than <c>bessel_i0(x)</c>.
        /// </remarks>
        public static Tensor bessel_i0e (Tensor x, string name = "BesselI0e")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("BesselI0e", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the Bessel i1e function of <c>x</c> element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BesselI1e'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Exponentially scaled modified Bessel function of order 0 defined as
        ///    <c>bessel_i1e(x) = exp(-abs(x)) bessel_i1(x)</c>.
        ///    
        ///    This function is faster and numerically stabler than <c>bessel_i1(x)</c>.
        /// </remarks>
        public static Tensor bessel_i1e (Tensor x, string name = "BesselI1e")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("BesselI1e", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Compute the regularized incomplete beta integral \\(I_x(a, b)\\).
        /// </summary>
        /// <param name="a">
        /// </param>
        /// <param name="b">
        /// </param>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Betainc'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The regularized incomplete beta integral is defined as:
        ///    
        ///    
        ///    \\(I_x(a, b) = \frac{B(x; a, b)}{B(a, b)}\\)
        ///    
        ///    where
        ///    
        ///    
        ///    \\(B(x; a, b) = \int_0^x t^{a-1} (1 - t)^{b-1} dt\\)
        ///    
        ///    
        ///    is the incomplete beta function and \\(B(a, b)\\) is the *complete*
        ///    beta function.
        /// </remarks>
        public static Tensor betainc (Tensor a, Tensor b, Tensor x, string name = "Betainc")
        {
            var dict = new Dictionary<string, object>();
            dict["a"] = a;
            dict["b"] = b;
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Betainc", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Adds <c>bias</c> to <c>value</c>.
        /// </summary>
        /// <param name="value">
        ///    Any number of dimensions.
        /// </param>
        /// <param name="bias">
        ///    1-D with size the last dimension of <c>value</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BiasAdd'.
        /// </param>
        /// <param name="data_format">
        ///    Specify the data format of the input and output data. With the
        ///    default format "NHWC", the bias tensor will be added to the last dimension
        ///    of the value tensor.
        ///    Alternatively, the format could be "NCHW", the data storage order of:
        ///    [batch, in_channels, in_height, in_width].
        ///    The tensor will be added to "in_channels", the third-to-the-last
        ///    dimension.
        /// </param>
        /// <returns>
        ///    Broadcasted sum of <c>value</c> and <c>bias</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This is a special case of <c>tf.add</c> where <c>bias</c> is restricted to be 1-D.
        ///    Broadcasting is supported, so <c>value</c> may have any number of dimensions.
        /// </remarks>
        public static Tensor bias_add (Tensor value, Tensor bias, string data_format = null, string name = "BiasAdd")
        {
            var dict = new Dictionary<string, object>();
            dict["value"] = value;
            dict["bias"] = bias;
            if (data_format != null)
                dict["data_format"] = data_format;
            var op = _op_def_lib._apply_op_helper("BiasAdd", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    The backward operation for "BiasAdd" on the "bias" tensor.
        /// </summary>
        /// <param name="out_backprop">
        ///    Any number of dimensions.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BiasAddGrad'.
        /// </param>
        /// <param name="data_format">
        ///    Specify the data format of the input and output data. With the
        ///    default format "NHWC", the bias tensor will be added to the last dimension
        ///    of the value tensor.
        ///    Alternatively, the format could be "NCHW", the data storage order of:
        ///    [batch, in_channels, in_height, in_width].
        ///    The tensor will be added to "in_channels", the third-to-the-last
        ///    dimension.
        /// </param>
        /// <returns>
        ///    1-D with size the feature dimension of <c>out_backprop</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    It accumulates all the values from out_backprop into the feature dimension.
        ///    For NHWC data format, the feature dimension is the last. For NCHW data format,
        ///    the feature dimension is the third-to-last.
        /// </remarks>
        public static Tensor bias_add_grad (Tensor out_backprop, string data_format = null, string name = "BiasAddGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["out_backprop"] = out_backprop;
            if (data_format != null)
                dict["data_format"] = data_format;
            var op = _op_def_lib._apply_op_helper("BiasAddGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Adds <c>bias</c> to <c>value</c>.
        /// </summary>
        /// <param name="value">
        ///    Any number of dimensions.
        /// </param>
        /// <param name="bias">
        ///    1-D with size the last dimension of <c>value</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BiasAddV1'.
        /// </param>
        /// <returns>
        ///    Broadcasted sum of <c>value</c> and <c>bias</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This is a deprecated version of BiasAdd and will be soon removed.
        ///    
        ///    This is a special case of <c>tf.add</c> where <c>bias</c> is restricted to be 1-D.
        ///    Broadcasting is supported, so <c>value</c> may have any number of dimensions.
        /// </remarks>
        public static Tensor bias_add_v1 (Tensor value, Tensor bias, string name = "BiasAddV1")
        {
            var dict = new Dictionary<string, object>();
            dict["value"] = value;
            dict["bias"] = bias;
            var op = _op_def_lib._apply_op_helper("BiasAddV1", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Counts the number of occurrences of each value in an integer array.
        /// </summary>
        /// <param name="arr">
        ///    int32 <c>Tensor</c>.
        /// </param>
        /// <param name="size">
        ///    non-negative int32 scalar <c>Tensor</c>.
        /// </param>
        /// <param name="weights">
        ///    is an int32, int64, float32, or float64 <c>Tensor</c> with the same
        ///    shape as <c>arr</c>, or a length-0 <c>Tensor</c>, in which case it acts as all weights
        ///    equal to 1.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Bincount'.
        /// </param>
        /// <returns>
        ///    1D <c>Tensor</c> with length equal to <c>size</c>. The counts or summed weights for
        ///    each value in the range [0, size).
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Outputs a vector with length <c>size</c> and the same dtype as <c>weights</c>. If
        ///    <c>weights</c> are empty, then index <c>i</c> stores the number of times the value <c>i</c> is
        ///    counted in <c>arr</c>. If <c>weights</c> are non-empty, then index <c>i</c> stores the sum of
        ///    the value in <c>weights</c> at each index where the corresponding value in <c>arr</c> is
        ///    <c>i</c>.
        ///    
        ///    Values in <c>arr</c> outside of the range [0, size) are ignored.
        /// </remarks>
        public static Tensor bincount (Tensor arr, Tensor size, Tensor weights, string name = "Bincount")
        {
            var dict = new Dictionary<string, object>();
            dict["arr"] = arr;
            dict["size"] = size;
            dict["weights"] = weights;
            var op = _op_def_lib._apply_op_helper("Bincount", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Bitcasts a tensor from one type to another without copying data.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Bitcast'.
        /// </param>
        /// <param name="type">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given a tensor <c>input</c>, this operation returns a tensor that has the same buffer
        ///    data as <c>input</c> with datatype <c>type</c>.
        ///    
        ///    If the input datatype <c>T</c> is larger than the output datatype <c>type</c> then the
        ///    shape changes from [...] to [..., sizeof(<c>T</c>)/sizeof(<c>type</c>)].
        ///    
        ///    If <c>T</c> is smaller than <c>type</c>, the operator requires that the rightmost
        ///    dimension be equal to sizeof(<c>type</c>)/sizeof(<c>T</c>). The shape then goes from
        ///    [..., sizeof(<c>type</c>)/sizeof(<c>T</c>)] to [...].
        ///    
        ///    *NOTE*: Bitcast is implemented as a low-level cast, so machines with different
        ///    endian orderings will give different results.
        /// </remarks>
        public static Tensor bitcast (Tensor input, TF_DataType type, string name = "Bitcast")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["type"] = type;
            var op = _op_def_lib._apply_op_helper("Bitcast", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Elementwise computes the bitwise AND of <c>x</c> and <c>y</c>.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BitwiseAnd'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The result will have those bits set, that are set in both <c>x</c> and <c>y</c>. The
        ///    computation is performed on the underlying representations of <c>x</c> and <c>y</c>.
        /// </remarks>
        public static Tensor bitwise_and (Tensor x, Tensor y, string name = "BitwiseAnd")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("BitwiseAnd", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Elementwise computes the bitwise OR of <c>x</c> and <c>y</c>.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BitwiseOr'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The result will have those bits set, that are set in <c>x</c>, <c>y</c> or both. The
        ///    computation is performed on the underlying representations of <c>x</c> and <c>y</c>.
        /// </remarks>
        public static Tensor bitwise_or (Tensor x, Tensor y, string name = "BitwiseOr")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("BitwiseOr", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Elementwise computes the bitwise XOR of <c>x</c> and <c>y</c>.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BitwiseXor'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The result will have those bits set, that are different in <c>x</c> and <c>y</c>. The
        ///    computation is performed on the underlying representations of <c>x</c> and <c>y</c>.
        /// </remarks>
        public static Tensor bitwise_xor (Tensor x, Tensor y, string name = "BitwiseXor")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("BitwiseXor", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Calculates gains for each feature and returns the best possible split information for the feature.
        /// </summary>
        /// <param name="node_id_range">
        ///    A Rank 1 tensor (shape=[2]) to specify the range [first, last) of node ids to process within <c>stats_summary_list</c>. The nodes are iterated between the two nodes specified by the tensor, as like <c>for node_id in range(node_id_range[0], node_id_range[1])</c> (Note that the last index node_id_range[1] is exclusive).
        /// </param>
        /// <param name="stats_summary_list">
        ///    A list of Rank 3 tensor (#shape=[max_splits, bucket, 2]) for accumulated stats summary (gradient/hessian) per node per buckets for each feature. The first dimension of the tensor is the maximum number of splits, and thus not all elements of it will be used, but only the indexes specified by node_ids will be used.
        /// </param>
        /// <param name="l1">
        ///    l1 regularization factor on leaf weights, per instance based.
        /// </param>
        /// <param name="l2">
        ///    l2 regularization factor on leaf weights, per instance based.
        /// </param>
        /// <param name="tree_complexity">
        ///    adjustment to the gain, per leaf based.
        /// </param>
        /// <param name="min_node_weight">
        ///    mininum avg of hessians in a node before required for the node to be considered for splitting.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BoostedTreesCalculateBestGainsPerFeature'.
        /// </param>
        /// <param name="max_splits">
        ///    Optional argument
        ///    the number of nodes that can be split in the whole tree. Used as a dimension of output tensors.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    node_ids_list : An output list of Rank 1 tensors indicating possible split node ids for each feature. The length of the list is num_features, but each tensor has different size as each feature provides different possible nodes. See above for details like shapes and sizes.
        ///    gains_list : An output list of Rank 1 tensors indicating the best gains for each feature to split for certain nodes. See above for details like shapes and sizes.
        ///    thresholds_list : An output list of Rank 1 tensors indicating the bucket id to compare with (as a threshold) for split in each node. See above for details like shapes and sizes.
        ///    left_node_contribs_list : A list of Rank 2 tensors indicating the contribution of the left nodes when branching from parent nodes (given by the tensor element in the output node_ids_list) to the left direction by the given threshold for each feature. This value will be used to make the left node value by adding to the parent node value. Second dimension size is 1 for 1-dimensional logits, but would be larger for multi-class problems. See above for details like shapes and sizes.
        ///    right_node_contribs_list : A list of Rank 2 tensors, with the same shape/conditions as left_node_contribs_list, but just that the value is for the right node.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    The split information is the best threshold (bucket id), gains and left/right node contributions per node for each feature.
        ///    
        ///    It is possible that not all nodes can be split on each feature. Hence, the list of possible nodes can differ between the features. Therefore, we return <c>node_ids_list</c> for each feature, containing the list of nodes that this feature can be used to split.
        ///    
        ///    In this manner, the output is the best split per features and per node, so that it needs to be combined later to produce the best split for each node (among all possible features).
        ///    
        ///    The length of output lists are all of the same length, <c>num_features</c>.
        ///    The output shapes are compatible in a way that the first dimension of all tensors of all lists are the same and equal to the number of possible split nodes for each feature.
        /// </remarks>
        public static (Tensor[] node_ids_list, Tensor[] gains_list, Tensor[] thresholds_list, Tensor[] left_node_contribs_list, Tensor[] right_node_contribs_list) boosted_trees_calculate_best_gains_per_feature (Tensor node_id_range, Tensor[] stats_summary_list, Tensor l1, Tensor l2, Tensor tree_complexity, Tensor min_node_weight, int max_splits, string name = "BoostedTreesCalculateBestGainsPerFeature")
        {
            var dict = new Dictionary<string, object>();
            dict["node_id_range"] = node_id_range;
            dict["stats_summary_list"] = stats_summary_list;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["tree_complexity"] = tree_complexity;
            dict["min_node_weight"] = min_node_weight;
            dict["max_splits"] = max_splits;
            var op = _op_def_lib._apply_op_helper("BoostedTreesCalculateBestGainsPerFeature", name: name, keywords: dict);
            int _idx = 0;
            var node_ids_list = Enumerable.Range(0, op.OutputListLength("node_ids_list")).Select(_ => op.outputs[_idx++]).ToArray();
            var gains_list = Enumerable.Range(0, op.OutputListLength("gains_list")).Select(_ => op.outputs[_idx++]).ToArray();
            var thresholds_list = Enumerable.Range(0, op.OutputListLength("thresholds_list")).Select(_ => op.outputs[_idx++]).ToArray();
            var left_node_contribs_list = Enumerable.Range(0, op.OutputListLength("left_node_contribs_list")).Select(_ => op.outputs[_idx++]).ToArray();
            var right_node_contribs_list = Enumerable.Range(0, op.OutputListLength("right_node_contribs_list")).Select(_ => op.outputs[_idx++]).ToArray();
            return (node_ids_list, gains_list, thresholds_list, left_node_contribs_list, right_node_contribs_list);
        }

        /// <summary>
        ///    Calculates the prior from the training data (the bias) and fills in the first node with the logits' prior. Returns a boolean indicating whether to continue centering.
        /// </summary>
        /// <param name="tree_ensemble_handle">
        ///    Handle to the tree ensemble.
        /// </param>
        /// <param name="mean_gradients">
        ///    A tensor with shape=[logits_dimension] with mean of gradients for a first node.
        /// </param>
        /// <param name="mean_hessians">
        ///    A tensor with shape=[logits_dimension] mean of hessians for a first node.
        /// </param>
        /// <param name="l1">
        ///    l1 regularization factor on leaf weights, per instance based.
        /// </param>
        /// <param name="l2">
        ///    l2 regularization factor on leaf weights, per instance based.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BoostedTreesCenterBias'.
        /// </param>
        /// <returns>
        ///    Bool, whether to continue bias centering.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor boosted_trees_center_bias (Tensor tree_ensemble_handle, Tensor mean_gradients, Tensor mean_hessians, Tensor l1, Tensor l2, string name = "BoostedTreesCenterBias")
        {
            var dict = new Dictionary<string, object>();
            dict["tree_ensemble_handle"] = tree_ensemble_handle;
            dict["mean_gradients"] = mean_gradients;
            dict["mean_hessians"] = mean_hessians;
            dict["l1"] = l1;
            dict["l2"] = l2;
            var op = _op_def_lib._apply_op_helper("BoostedTreesCenterBias", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a tree ensemble model and returns a handle to it.
        /// </summary>
        /// <param name="tree_ensemble_handle">
        ///    Handle to the tree ensemble resource to be created.
        /// </param>
        /// <param name="stamp_token">
        ///    Token to use as the initial value of the resource stamp.
        /// </param>
        /// <param name="tree_ensemble_serialized">
        ///    Serialized proto of the tree ensemble.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BoostedTreesCreateEnsemble'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation boosted_trees_create_ensemble (Tensor tree_ensemble_handle, Tensor stamp_token, Tensor tree_ensemble_serialized, string name = "BoostedTreesCreateEnsemble")
        {
            var dict = new Dictionary<string, object>();
            dict["tree_ensemble_handle"] = tree_ensemble_handle;
            dict["stamp_token"] = stamp_token;
            dict["tree_ensemble_serialized"] = tree_ensemble_serialized;
            var op = _op_def_lib._apply_op_helper("BoostedTreesCreateEnsemble", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Deserializes a serialized tree ensemble config and replaces current tree
        /// </summary>
        /// <param name="tree_ensemble_handle">
        ///    Handle to the tree ensemble.
        /// </param>
        /// <param name="stamp_token">
        ///    Token to use as the new value of the resource stamp.
        /// </param>
        /// <param name="tree_ensemble_serialized">
        ///    Serialized proto of the ensemble.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BoostedTreesDeserializeEnsemble'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    ensemble.
        /// </remarks>
        public static Operation boosted_trees_deserialize_ensemble (Tensor tree_ensemble_handle, Tensor stamp_token, Tensor tree_ensemble_serialized, string name = "BoostedTreesDeserializeEnsemble")
        {
            var dict = new Dictionary<string, object>();
            dict["tree_ensemble_handle"] = tree_ensemble_handle;
            dict["stamp_token"] = stamp_token;
            dict["tree_ensemble_serialized"] = tree_ensemble_serialized;
            var op = _op_def_lib._apply_op_helper("BoostedTreesDeserializeEnsemble", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Creates a handle to a BoostedTreesEnsembleResource
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BoostedTreesEnsembleResourceHandleOp'.
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor boosted_trees_ensemble_resource_handle_op (string container = null, string shared_name = null, string name = "BoostedTreesEnsembleResourceHandleOp")
        {
            var dict = new Dictionary<string, object>();
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("BoostedTreesEnsembleResourceHandleOp", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Debugging/model interpretability outputs for each example.
        /// </summary>
        /// <param name="tree_ensemble_handle">
        /// </param>
        /// <param name="bucketized_features">
        ///    A list of rank 1 Tensors containing bucket id for each
        ///    feature.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BoostedTreesExampleDebugOutputs'.
        /// </param>
        /// <param name="logits_dimension">
        ///    Optional argument
        ///    scalar, dimension of the logits, to be used for constructing the protos in
        ///    examples_debug_outputs_serialized.
        /// </param>
        /// <returns>
        ///    Output rank 1 Tensor containing a proto serialized as a string for each example.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    It traverses all the trees and computes debug metrics for individual examples,
        ///    such as getting split feature ids and logits after each split along the decision
        ///    path used to compute directional feature contributions.
        /// </remarks>
        public static Tensor boosted_trees_example_debug_outputs (Tensor tree_ensemble_handle, Tensor[] bucketized_features, int logits_dimension, string name = "BoostedTreesExampleDebugOutputs")
        {
            var dict = new Dictionary<string, object>();
            dict["tree_ensemble_handle"] = tree_ensemble_handle;
            dict["bucketized_features"] = bucketized_features;
            dict["logits_dimension"] = logits_dimension;
            var op = _op_def_lib._apply_op_helper("BoostedTreesExampleDebugOutputs", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Retrieves the tree ensemble resource stamp token, number of trees and growing statistics.
        /// </summary>
        /// <param name="tree_ensemble_handle">
        ///    Handle to the tree ensemble.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BoostedTreesGetEnsembleStates'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    stamp_token : Stamp token of the tree ensemble resource.
        ///    num_trees : The number of trees in the tree ensemble resource.
        ///    num_finalized_trees : The number of trees that were finished successfully.
        ///    num_attempted_layers : The number of layers we attempted to build (but not necessarily succeeded).
        ///    last_layer_nodes_range : Rank size 2 tensor that contains start and end ids of the nodes in the latest
        ///    layer.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor stamp_token, Tensor num_trees, Tensor num_finalized_trees, Tensor num_attempted_layers, Tensor last_layer_nodes_range) boosted_trees_get_ensemble_states (Tensor tree_ensemble_handle, string name = "BoostedTreesGetEnsembleStates")
        {
            var dict = new Dictionary<string, object>();
            dict["tree_ensemble_handle"] = tree_ensemble_handle;
            var op = _op_def_lib._apply_op_helper("BoostedTreesGetEnsembleStates", name: name, keywords: dict);
            int _idx = 0;
            var stamp_token = op.outputs[_idx++];
            var num_trees = op.outputs[_idx++];
            var num_finalized_trees = op.outputs[_idx++];
            var num_attempted_layers = op.outputs[_idx++];
            var last_layer_nodes_range = op.outputs[_idx++];
            return (stamp_token, num_trees, num_finalized_trees, num_attempted_layers, last_layer_nodes_range);
        }

        /// <summary>
        ///    Makes the summary of accumulated stats for the batch.
        /// </summary>
        /// <param name="node_ids">
        ///    int32 Rank 1 Tensor containing node ids, which each example falls into for the requested layer.
        /// </param>
        /// <param name="gradients">
        ///    float32; Rank 2 Tensor (shape=[#examples, 1]) for gradients.
        /// </param>
        /// <param name="hessians">
        ///    float32; Rank 2 Tensor (shape=[#examples, 1]) for hessians.
        /// </param>
        /// <param name="bucketized_features_list">
        ///    int32 list of Rank 1 Tensors, each containing the bucketized feature (for each feature column).
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BoostedTreesMakeStatsSummary'.
        /// </param>
        /// <param name="max_splits">
        ///    Optional argument
        ///    int; the maximum number of splits possible in the whole tree.
        /// </param>
        /// <param name="num_buckets">
        ///    Optional argument
        ///    int; equals to the maximum possible value of bucketized feature.
        /// </param>
        /// <returns>
        ///    output Rank 4 Tensor (shape=[#features, #splits, #buckets, 2]) containing accumulated stats put into the corresponding node and bucket. The first index of 4th dimension refers to gradients, and the second to hessians.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The summary stats contains gradients and hessians accumulated into the corresponding node and bucket for each example.
        /// </remarks>
        public static Tensor boosted_trees_make_stats_summary (Tensor node_ids, Tensor gradients, Tensor hessians, Tensor[] bucketized_features_list, int max_splits, int num_buckets, string name = "BoostedTreesMakeStatsSummary")
        {
            var dict = new Dictionary<string, object>();
            dict["node_ids"] = node_ids;
            dict["gradients"] = gradients;
            dict["hessians"] = hessians;
            dict["bucketized_features_list"] = bucketized_features_list;
            dict["max_splits"] = max_splits;
            dict["num_buckets"] = num_buckets;
            var op = _op_def_lib._apply_op_helper("BoostedTreesMakeStatsSummary", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Runs multiple additive regression ensemble predictors on input instances and
        /// </summary>
        /// <param name="tree_ensemble_handle">
        /// </param>
        /// <param name="bucketized_features">
        ///    A list of rank 1 Tensors containing bucket id for each
        ///    feature.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BoostedTreesPredict'.
        /// </param>
        /// <param name="logits_dimension">
        ///    Optional argument
        ///    scalar, dimension of the logits, to be used for partial logits
        ///    shape.
        /// </param>
        /// <returns>
        ///    Output rank 2 Tensor containing logits for each example.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    computes the logits. It is designed to be used during prediction.
        ///    It traverses all the trees and calculates the final score for each instance.
        /// </remarks>
        public static Tensor boosted_trees_predict (Tensor tree_ensemble_handle, Tensor[] bucketized_features, int logits_dimension, string name = "BoostedTreesPredict")
        {
            var dict = new Dictionary<string, object>();
            dict["tree_ensemble_handle"] = tree_ensemble_handle;
            dict["bucketized_features"] = bucketized_features;
            dict["logits_dimension"] = logits_dimension;
            var op = _op_def_lib._apply_op_helper("BoostedTreesPredict", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Serializes the tree ensemble to a proto.
        /// </summary>
        /// <param name="tree_ensemble_handle">
        ///    Handle to the tree ensemble.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BoostedTreesSerializeEnsemble'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    stamp_token : Stamp token of the tree ensemble resource.
        ///    tree_ensemble_serialized : Serialized proto of the ensemble.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor stamp_token, Tensor tree_ensemble_serialized) boosted_trees_serialize_ensemble (Tensor tree_ensemble_handle, string name = "BoostedTreesSerializeEnsemble")
        {
            var dict = new Dictionary<string, object>();
            dict["tree_ensemble_handle"] = tree_ensemble_handle;
            var op = _op_def_lib._apply_op_helper("BoostedTreesSerializeEnsemble", name: name, keywords: dict);
            int _idx = 0;
            var stamp_token = op.outputs[_idx++];
            var tree_ensemble_serialized = op.outputs[_idx++];
            return (stamp_token, tree_ensemble_serialized);
        }

        /// <summary>
        ///    Runs multiple additive regression ensemble predictors on input instances and
        /// </summary>
        /// <param name="tree_ensemble_handle">
        /// </param>
        /// <param name="cached_tree_ids">
        ///    Rank 1 Tensor containing cached tree ids which is the starting
        ///    tree of prediction.
        /// </param>
        /// <param name="cached_node_ids">
        ///    Rank 1 Tensor containing cached node id which is the starting
        ///    node of prediction.
        /// </param>
        /// <param name="bucketized_features">
        ///    A list of rank 1 Tensors containing bucket id for each
        ///    feature.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BoostedTreesTrainingPredict'.
        /// </param>
        /// <param name="logits_dimension">
        ///    Optional argument
        ///    scalar, dimension of the logits, to be used for partial logits
        ///    shape.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    partial_logits : Rank 2 Tensor containing logits update (with respect to cached
        ///    values stored) for each example.
        ///    tree_ids : Rank 1 Tensor containing new tree ids for each example.
        ///    node_ids : Rank 1 Tensor containing new node ids in the new tree_ids.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    computes the update to cached logits. It is designed to be used during training.
        ///    It traverses the trees starting from cached tree id and cached node id and
        ///    calculates the updates to be pushed to the cache.
        /// </remarks>
        public static (Tensor partial_logits, Tensor tree_ids, Tensor node_ids) boosted_trees_training_predict (Tensor tree_ensemble_handle, Tensor cached_tree_ids, Tensor cached_node_ids, Tensor[] bucketized_features, int logits_dimension, string name = "BoostedTreesTrainingPredict")
        {
            var dict = new Dictionary<string, object>();
            dict["tree_ensemble_handle"] = tree_ensemble_handle;
            dict["cached_tree_ids"] = cached_tree_ids;
            dict["cached_node_ids"] = cached_node_ids;
            dict["bucketized_features"] = bucketized_features;
            dict["logits_dimension"] = logits_dimension;
            var op = _op_def_lib._apply_op_helper("BoostedTreesTrainingPredict", name: name, keywords: dict);
            int _idx = 0;
            var partial_logits = op.outputs[_idx++];
            var tree_ids = op.outputs[_idx++];
            var node_ids = op.outputs[_idx++];
            return (partial_logits, tree_ids, node_ids);
        }

        /// <summary>
        ///    Updates the tree ensemble by either adding a layer to the last tree being grown
        /// </summary>
        /// <param name="tree_ensemble_handle">
        ///    Handle to the ensemble variable.
        /// </param>
        /// <param name="feature_ids">
        ///    Rank 1 tensor with ids for each feature. This is the real id of
        ///    the feature that will be used in the split.
        /// </param>
        /// <param name="node_ids">
        ///    List of rank 1 tensors representing the nodes for which this feature
        ///    has a split.
        /// </param>
        /// <param name="gains">
        ///    List of rank 1 tensors representing the gains for each of the feature's
        ///    split.
        /// </param>
        /// <param name="thresholds">
        ///    List of rank 1 tensors representing the thesholds for each of the
        ///    feature's split.
        /// </param>
        /// <param name="left_node_contribs">
        ///    List of rank 2 tensors with left leaf contribs for each of
        ///    the feature's splits. Will be added to the previous node values to constitute
        ///    the values of the left nodes.
        /// </param>
        /// <param name="right_node_contribs">
        ///    List of rank 2 tensors with right leaf contribs for each
        ///    of the feature's splits. Will be added to the previous node values to constitute
        ///    the values of the right nodes.
        /// </param>
        /// <param name="max_depth">
        ///    Max depth of the tree to build.
        /// </param>
        /// <param name="learning_rate">
        ///    shrinkage const for each new tree.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BoostedTreesUpdateEnsemble'.
        /// </param>
        /// <param name="pruning_mode">
        ///    Optional argument
        ///    0-No pruning, 1-Pre-pruning, 2-Post-pruning.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    or by starting a new tree.
        /// </remarks>
        public static Operation boosted_trees_update_ensemble (Tensor tree_ensemble_handle, Tensor feature_ids, Tensor[] node_ids, Tensor[] gains, Tensor[] thresholds, Tensor[] left_node_contribs, Tensor[] right_node_contribs, Tensor max_depth, Tensor learning_rate, int pruning_mode, string name = "BoostedTreesUpdateEnsemble")
        {
            var dict = new Dictionary<string, object>();
            dict["tree_ensemble_handle"] = tree_ensemble_handle;
            dict["feature_ids"] = feature_ids;
            dict["node_ids"] = node_ids;
            dict["gains"] = gains;
            dict["thresholds"] = thresholds;
            dict["left_node_contribs"] = left_node_contribs;
            dict["right_node_contribs"] = right_node_contribs;
            dict["max_depth"] = max_depth;
            dict["learning_rate"] = learning_rate;
            dict["pruning_mode"] = pruning_mode;
            var op = _op_def_lib._apply_op_helper("BoostedTreesUpdateEnsemble", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Return the shape of s0 op s1 with broadcast.
        /// </summary>
        /// <param name="s0">
        /// </param>
        /// <param name="s1">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BroadcastArgs'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given <c>s0</c> and <c>s1</c>, tensors that represent shapes, compute <c>r0</c>, the
        ///    broadcasted shape. <c>s0</c>, <c>s1</c> and <c>r0</c> are all integer vectors.
        /// </remarks>
        public static Tensor broadcast_args (Tensor s0, Tensor s1, string name = "BroadcastArgs")
        {
            var dict = new Dictionary<string, object>();
            dict["s0"] = s0;
            dict["s1"] = s1;
            var op = _op_def_lib._apply_op_helper("BroadcastArgs", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Return the reduction indices for computing gradients of s0 op s1 with broadcast.
        /// </summary>
        /// <param name="s0">
        /// </param>
        /// <param name="s1">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BroadcastGradientArgs'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    r0 :
        ///    r1 :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    This is typically used by gradient computations for a broadcasting operation.
        /// </remarks>
        public static (Tensor r0, Tensor r1) broadcast_gradient_args (Tensor s0, Tensor s1, string name = "BroadcastGradientArgs")
        {
            var dict = new Dictionary<string, object>();
            dict["s0"] = s0;
            dict["s1"] = s1;
            var op = _op_def_lib._apply_op_helper("BroadcastGradientArgs", name: name, keywords: dict);
            int _idx = 0;
            var r0 = op.outputs[_idx++];
            var r1 = op.outputs[_idx++];
            return (r0, r1);
        }

        /// <summary>
        ///    Broadcast an array for a compatible shape.
        /// </summary>
        /// <param name="input">
        ///    A Tensor to broadcast.
        /// </param>
        /// <param name="shape">
        ///    An 1-D <c>int</c> Tensor. The shape of the desired output.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BroadcastTo'.
        /// </param>
        /// <returns>
        ///    A Tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Broadcasting is the process of making arrays to have compatible shapes
        ///    for arithmetic operations. Two shapes are compatible if for each
        ///    dimension pair they are either equal or one of them is one. When trying
        ///    to broadcast a Tensor to a shape, it starts with the trailing dimensions,
        ///    and works its way forward.
        ///    
        ///    For example,
        ///   <code>
        ///    &amp;gt;&amp;gt;&amp;gt; x = tf.constant([1, 2, 3])
        ///    &amp;gt;&amp;gt;&amp;gt; y = tf.broadcast_to(x, [3, 3])
        ///    &amp;gt;&amp;gt;&amp;gt; sess.run(y)
        ///    array([[1, 2, 3],
        ///    [1, 2, 3],
        ///    [1, 2, 3]], dtype=int32)
        ///   </code>
        ///    In the above example, the input Tensor with the shape of <c>[1, 3]</c>
        ///    is broadcasted to output Tensor with shape of <c>[3, 3]</c>.
        /// </remarks>
        public static Tensor broadcast_to (Tensor input, Tensor shape, string name = "BroadcastTo")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["shape"] = shape;
            var op = _op_def_lib._apply_op_helper("BroadcastTo", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Bucketizes 'input' based on 'boundaries'.
        /// </summary>
        /// <param name="input">
        ///    Any shape of Tensor contains with int or float type.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Bucketize'.
        /// </param>
        /// <param name="boundaries">
        ///    Optional argument
        ///    A sorted list of floats gives the boundary of the buckets.
        /// </param>
        /// <returns>
        ///    Same shape with 'input', each value of input replaced with bucket index.
        ///    
        ///    @compatibility(numpy)
        ///    Equivalent to np.digitize.
        ///    @end_compatibility
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    For example, if the inputs are
        ///    boundaries = [0, 10, 100]
        ///    input = [[-5, 10000]
        ///    [150,   10]
        ///    [5,    100]]
        ///    
        ///    then the output will be
        ///    output = [[0, 3]
        ///    [3, 2]
        ///    [1, 3]]
        /// </remarks>
        public static Tensor bucketize (Tensor input, float[] boundaries, string name = "Bucketize")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["boundaries"] = boundaries;
            var op = _op_def_lib._apply_op_helper("Bucketize", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Records the bytes size of each element of <c>input_dataset</c> in a StatsAggregator.
        /// </summary>
        /// <param name="input_dataset">
        /// </param>
        /// <param name="tag">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'BytesProducedStatsDataset'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor bytes_produced_stats_dataset (Tensor input_dataset, Tensor tag, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "BytesProducedStatsDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["tag"] = tag;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("BytesProducedStatsDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Performs beam search decoding on the logits given in input.
        /// </summary>
        /// <param name="inputs">
        ///    3-D, shape: <c>(max_time x batch_size x num_classes)</c>, the logits.
        /// </param>
        /// <param name="sequence_length">
        ///    A vector containing sequence lengths, size <c>(batch)</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CTCBeamSearchDecoder'.
        /// </param>
        /// <param name="beam_width">
        ///    Optional argument
        ///    A scalar &amp;gt;= 0 (beam search beam width).
        /// </param>
        /// <param name="top_paths">
        ///    Optional argument
        ///    A scalar &amp;gt;= 0, &amp;lt;= beam_width (controls output size).
        /// </param>
        /// <param name="merge_repeated">
        ///    If true, merge repeated classes in output.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    decoded_indices : A list (length: top_paths) of indices matrices.  Matrix j,
        ///    size <c>(total_decoded_outputs[j] x 2)</c>, has indices of a
        ///    <c>SparseTensor&amp;lt;int64, 2&amp;gt;</c>.  The rows store: [batch, time].
        ///    decoded_values : A list (length: top_paths) of values vectors.  Vector j,
        ///    size <c>(length total_decoded_outputs[j])</c>, has the values of a
        ///    <c>SparseTensor&amp;lt;int64, 2&amp;gt;</c>.  The vector stores the decoded classes for beam j.
        ///    decoded_shape : A list (length: top_paths) of shape vector.  Vector j,
        ///    size <c>(2)</c>, stores the shape of the decoded <c>SparseTensor[j]</c>.
        ///    Its values are: <c>[batch_size, max_decoded_length[j]]</c>.
        ///    log_probability : A matrix, shaped: <c>(batch_size x top_paths)</c>.  The
        ///    sequence log-probabilities.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    A note about the attribute merge_repeated: For the beam search decoder,
        ///    this means that if consecutive entries in a beam are the same, only
        ///    the first of these is emitted.  That is, when the top path is "A B B B B",
        ///    "A B" is returned if merge_repeated = True but "A B B B B" is
        ///    returned if merge_repeated = False.
        /// </remarks>
        public static (Tensor[] decoded_indices, Tensor[] decoded_values, Tensor[] decoded_shape, Tensor log_probability) c_t_c_beam_search_decoder (Tensor inputs, Tensor sequence_length, int beam_width, int top_paths, bool? merge_repeated = null, string name = "CTCBeamSearchDecoder")
        {
            var dict = new Dictionary<string, object>();
            dict["inputs"] = inputs;
            dict["sequence_length"] = sequence_length;
            dict["beam_width"] = beam_width;
            dict["top_paths"] = top_paths;
            if (merge_repeated.HasValue)
                dict["merge_repeated"] = merge_repeated.Value;
            var op = _op_def_lib._apply_op_helper("CTCBeamSearchDecoder", name: name, keywords: dict);
            int _idx = 0;
            var decoded_indices = Enumerable.Range(0, op.OutputListLength("decoded_indices")).Select(_ => op.outputs[_idx++]).ToArray();
            var decoded_values = Enumerable.Range(0, op.OutputListLength("decoded_values")).Select(_ => op.outputs[_idx++]).ToArray();
            var decoded_shape = Enumerable.Range(0, op.OutputListLength("decoded_shape")).Select(_ => op.outputs[_idx++]).ToArray();
            var log_probability = op.outputs[_idx++];
            return (decoded_indices, decoded_values, decoded_shape, log_probability);
        }

        /// <summary>
        ///    Performs greedy decoding on the logits given in inputs.
        /// </summary>
        /// <param name="inputs">
        ///    3-D, shape: <c>(max_time x batch_size x num_classes)</c>, the logits.
        /// </param>
        /// <param name="sequence_length">
        ///    A vector containing sequence lengths, size <c>(batch_size)</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CTCGreedyDecoder'.
        /// </param>
        /// <param name="merge_repeated">
        ///    If True, merge repeated classes in output.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    decoded_indices : Indices matrix, size <c>(total_decoded_outputs x 2)</c>,
        ///    of a <c>SparseTensor&amp;lt;int64, 2&amp;gt;</c>.  The rows store: [batch, time].
        ///    decoded_values : Values vector, size: <c>(total_decoded_outputs)</c>,
        ///    of a <c>SparseTensor&amp;lt;int64, 2&amp;gt;</c>.  The vector stores the decoded classes.
        ///    decoded_shape : Shape vector, size <c>(2)</c>, of the decoded SparseTensor.
        ///    Values are: <c>[batch_size, max_decoded_length]</c>.
        ///    log_probability : Matrix, size <c>(batch_size x 1)</c>, containing sequence
        ///    log-probabilities.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    A note about the attribute merge_repeated: if enabled, when
        ///    consecutive logits' maximum indices are the same, only the first of
        ///    these is emitted.  Labeling the blank '*', the sequence "A B B * B B"
        ///    becomes "A B B" if merge_repeated = True and "A B B B B" if
        ///    merge_repeated = False.
        ///    
        ///    Regardless of the value of merge_repeated, if the maximum index of a given
        ///    time and batch corresponds to the blank, index <c>(num_classes - 1)</c>, no new
        ///    element is emitted.
        /// </remarks>
        public static (Tensor decoded_indices, Tensor decoded_values, Tensor decoded_shape, Tensor log_probability) c_t_c_greedy_decoder (Tensor inputs, Tensor sequence_length, bool? merge_repeated = null, string name = "CTCGreedyDecoder")
        {
            var dict = new Dictionary<string, object>();
            dict["inputs"] = inputs;
            dict["sequence_length"] = sequence_length;
            if (merge_repeated.HasValue)
                dict["merge_repeated"] = merge_repeated.Value;
            var op = _op_def_lib._apply_op_helper("CTCGreedyDecoder", name: name, keywords: dict);
            int _idx = 0;
            var decoded_indices = op.outputs[_idx++];
            var decoded_values = op.outputs[_idx++];
            var decoded_shape = op.outputs[_idx++];
            var log_probability = op.outputs[_idx++];
            return (decoded_indices, decoded_values, decoded_shape, log_probability);
        }

        /// <summary>
        ///    Calculates the CTC Loss (log probability) for each batch entry.  Also calculates
        /// </summary>
        /// <param name="inputs">
        ///    3-D, shape: <c>(max_time x batch_size x num_classes)</c>, the logits.
        /// </param>
        /// <param name="labels_indices">
        ///    The indices of a <c>SparseTensor&amp;lt;int32, 2&amp;gt;</c>.
        ///    <c>labels_indices(i, :) == [b, t]</c> means <c>labels_values(i)</c> stores the id for
        ///    <c>(batch b, time t)</c>.
        /// </param>
        /// <param name="labels_values">
        ///    The values (labels) associated with the given batch and time.
        /// </param>
        /// <param name="sequence_length">
        ///    A vector containing sequence lengths (batch).
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CTCLoss'.
        /// </param>
        /// <param name="preprocess_collapse_repeated">
        ///    Scalar, if true then repeated labels are
        ///    collapsed prior to the CTC calculation.
        /// </param>
        /// <param name="ctc_merge_repeated">
        ///    Scalar.  If set to false, *during* CTC calculation
        ///    repeated non-blank labels will not be merged and are interpreted as
        ///    individual labels.  This is a simplified version of CTC.
        /// </param>
        /// <param name="ignore_longer_outputs_than_inputs">
        ///    Scalar. If set to true, during CTC
        ///    calculation, items that have longer output sequences than input sequences
        ///    are skipped: they don't contribute to the loss term and have zero-gradient.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    loss : A vector (batch) containing log-probabilities.
        ///    gradient : The gradient of <c>loss</c>.  3-D, shape:
        ///    <c>(max_time x batch_size x num_classes)</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    the gradient.  This class performs the softmax operation for you, so inputs
        ///    should be e.g. linear projections of outputs by an LSTM.
        /// </remarks>
        public static (Tensor loss, Tensor gradient) c_t_c_loss (Tensor inputs, Tensor labels_indices, Tensor labels_values, Tensor sequence_length, bool? preprocess_collapse_repeated = null, bool? ctc_merge_repeated = null, bool? ignore_longer_outputs_than_inputs = null, string name = "CTCLoss")
        {
            var dict = new Dictionary<string, object>();
            dict["inputs"] = inputs;
            dict["labels_indices"] = labels_indices;
            dict["labels_values"] = labels_values;
            dict["sequence_length"] = sequence_length;
            if (preprocess_collapse_repeated.HasValue)
                dict["preprocess_collapse_repeated"] = preprocess_collapse_repeated.Value;
            if (ctc_merge_repeated.HasValue)
                dict["ctc_merge_repeated"] = ctc_merge_repeated.Value;
            if (ignore_longer_outputs_than_inputs.HasValue)
                dict["ignore_longer_outputs_than_inputs"] = ignore_longer_outputs_than_inputs.Value;
            var op = _op_def_lib._apply_op_helper("CTCLoss", name: name, keywords: dict);
            int _idx = 0;
            var loss = op.outputs[_idx++];
            var gradient = op.outputs[_idx++];
            return (loss, gradient);
        }

        /// <summary>
        ///    Creates a dataset that caches elements from <c>input_dataset</c>.
        /// </summary>
        /// <param name="input_dataset">
        /// </param>
        /// <param name="filename">
        ///    A path on the filesystem where we should cache the dataset. Note: this
        ///    will be a directory.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CacheDataset'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    A CacheDataset will iterate over the input_dataset, and store tensors. If the
        ///    cache already exists, the cache will be used. If the cache is inappropriate
        ///    (e.g. cannot be opened, contains tensors of the wrong shape / size), an error
        ///    will the returned when used.
        /// </remarks>
        public static Tensor cache_dataset (Tensor input_dataset, Tensor filename, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "CacheDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["filename"] = filename;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("CacheDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Cast x of type SrcT to y of DstT.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Cast'.
        /// </param>
        /// <param name="DstT">
        ///    Optional argument
        /// </param>
        /// <param name="Truncate">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor cast (Tensor x, TF_DataType DstT, bool? Truncate = null, string name = "Cast")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["DstT"] = DstT;
            if (Truncate.HasValue)
                dict["Truncate"] = Truncate.Value;
            var op = _op_def_lib._apply_op_helper("Cast", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns element-wise smallest integer not less than x.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Ceil'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor ceil (Tensor x, string name = "Ceil")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Ceil", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Checks a tensor for NaN and Inf values.
        /// </summary>
        /// <param name="tensor">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CheckNumerics'.
        /// </param>
        /// <param name="message">
        ///    Optional argument
        ///    Prefix of the error message.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    When run, reports an <c>InvalidArgument</c> error if <c>tensor</c> has any values
        ///    that are not a number (NaN) or infinity (Inf). Otherwise, passes <c>tensor</c> as-is.
        /// </remarks>
        public static Tensor check_numerics (Tensor tensor, string message, string name = "CheckNumerics")
        {
            var dict = new Dictionary<string, object>();
            dict["tensor"] = tensor;
            dict["message"] = message;
            var op = _op_def_lib._apply_op_helper("CheckNumerics", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the Cholesky decomposition of one or more square matrices.
        /// </summary>
        /// <param name="input">
        ///    Shape is <c>[..., M, M]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Cholesky'.
        /// </param>
        /// <returns>
        ///    Shape is <c>[..., M, M]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The input is a tensor of shape <c>[..., M, M]</c> whose inner-most 2 dimensions
        ///    form square matrices.
        ///    
        ///    The input has to be symmetric and positive definite. Only the lower-triangular
        ///    part of the input will be used for this operation. The upper-triangular part
        ///    will not be read.
        ///    
        ///    The output is a tensor of the same shape as the input
        ///    containing the Cholesky decompositions for all input submatrices <c>[..., :, :]</c>.
        ///    
        ///    **Note**: The gradient computation on GPU is faster for large matrices but
        ///    not for large batch dimensions when the submatrices are small. In this
        ///    case it might be faster to use the CPU.
        /// </remarks>
        public static Tensor cholesky (Tensor input, string name = "Cholesky")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("Cholesky", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the reverse mode backpropagated gradient of the Cholesky algorithm.
        /// </summary>
        /// <param name="l">
        ///    Output of batch Cholesky algorithm l = cholesky(A). Shape is <c>[..., M, M]</c>.
        ///    Algorithm depends only on lower triangular part of the innermost matrices of
        ///    this tensor.
        /// </param>
        /// <param name="grad">
        ///    df/dl where f is some scalar function. Shape is <c>[..., M, M]</c>.
        ///    Algorithm depends only on lower triangular part of the innermost matrices of
        ///    this tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CholeskyGrad'.
        /// </param>
        /// <returns>
        ///    Symmetrized version of df/dA . Shape is <c>[..., M, M]</c>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    For an explanation see "Differentiation of the Cholesky algorithm" by
        ///    Iain Murray http://arxiv.org/abs/1602.07527.
        /// </remarks>
        public static Tensor cholesky_grad (Tensor l, Tensor grad, string name = "CholeskyGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["l"] = l;
            dict["grad"] = grad;
            var op = _op_def_lib._apply_op_helper("CholeskyGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Clips tensor values to a specified min and max.
        /// </summary>
        /// <param name="t">
        ///    A <c>Tensor</c>.
        /// </param>
        /// <param name="clip_value_min">
        ///    A 0-D (scalar) <c>Tensor</c>, or a <c>Tensor</c> with the same shape
        ///    as <c>t</c>. The minimum value to clip by.
        /// </param>
        /// <param name="clip_value_max">
        ///    A 0-D (scalar) <c>Tensor</c>, or a <c>Tensor</c> with the same shape
        ///    as <c>t</c>. The maximum value to clip by.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ClipByValue'.
        /// </param>
        /// <returns>
        ///    A clipped <c>Tensor</c> with the same shape as input 't'.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given a tensor <c>t</c>, this operation returns a tensor of the same type and
        ///    shape as <c>t</c> with its values clipped to <c>clip_value_min</c> and <c>clip_value_max</c>.
        ///    Any values less than <c>clip_value_min</c> are set to <c>clip_value_min</c>. Any values
        ///    greater than <c>clip_value_max</c> are set to <c>clip_value_max</c>.
        /// </remarks>
        public static Tensor clip_by_value (Tensor t, Tensor clip_value_min, Tensor clip_value_max, string name = "ClipByValue")
        {
            var dict = new Dictionary<string, object>();
            dict["t"] = t;
            dict["clip_value_min"] = clip_value_min;
            dict["clip_value_max"] = clip_value_max;
            var op = _op_def_lib._apply_op_helper("ClipByValue", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Receives a tensor value broadcast from another device.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CollectiveBcastRecv'.
        /// </param>
        /// <param name="T">
        ///    Optional argument
        /// </param>
        /// <param name="group_size">
        ///    Optional argument
        /// </param>
        /// <param name="group_key">
        ///    Optional argument
        /// </param>
        /// <param name="instance_key">
        ///    Optional argument
        /// </param>
        /// <param name="shape">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor collective_bcast_recv (TF_DataType T, int group_size, int group_key, int instance_key, TensorShape shape, string name = "CollectiveBcastRecv")
        {
            var dict = new Dictionary<string, object>();
            dict["T"] = T;
            dict["group_size"] = group_size;
            dict["group_key"] = group_key;
            dict["instance_key"] = instance_key;
            dict["shape"] = shape;
            var op = _op_def_lib._apply_op_helper("CollectiveBcastRecv", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Broadcasts a tensor value to one or more other devices.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CollectiveBcastSend'.
        /// </param>
        /// <param name="group_size">
        ///    Optional argument
        /// </param>
        /// <param name="group_key">
        ///    Optional argument
        /// </param>
        /// <param name="instance_key">
        ///    Optional argument
        /// </param>
        /// <param name="shape">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor collective_bcast_send (Tensor input, int group_size, int group_key, int instance_key, TensorShape shape, string name = "CollectiveBcastSend")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["group_size"] = group_size;
            dict["group_key"] = group_key;
            dict["instance_key"] = instance_key;
            dict["shape"] = shape;
            var op = _op_def_lib._apply_op_helper("CollectiveBcastSend", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Mutually reduces multiple tensors of identical type and shape.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CollectiveReduce'.
        /// </param>
        /// <param name="group_size">
        ///    Optional argument
        /// </param>
        /// <param name="group_key">
        ///    Optional argument
        /// </param>
        /// <param name="instance_key">
        ///    Optional argument
        /// </param>
        /// <param name="merge_op">
        ///    Optional argument
        /// </param>
        /// <param name="final_op">
        ///    Optional argument
        /// </param>
        /// <param name="subdiv_offsets">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor collective_reduce (Tensor input, int group_size, int group_key, int instance_key, string merge_op, string final_op, int[] subdiv_offsets, string name = "CollectiveReduce")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["group_size"] = group_size;
            dict["group_key"] = group_key;
            dict["instance_key"] = instance_key;
            dict["merge_op"] = merge_op;
            dict["final_op"] = final_op;
            dict["subdiv_offsets"] = subdiv_offsets;
            var op = _op_def_lib._apply_op_helper("CollectiveReduce", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Compare values of <c>input</c> to <c>threshold</c> and pack resulting bits into a <c>uint8</c>.
        /// </summary>
        /// <param name="input">
        ///    Values to compare against <c>threshold</c> and bitpack.
        /// </param>
        /// <param name="threshold">
        ///    Threshold to compare against.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CompareAndBitpack'.
        /// </param>
        /// <returns>
        ///    The bitpacked comparisons.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Each comparison returns a boolean <c>true</c> (if <c>input_value &amp;gt; threshold</c>)
        ///    or and <c>false</c> otherwise.
        ///    
        ///    This operation is useful for Locality-Sensitive-Hashing (LSH) and other
        ///    algorithms that use hashing approximations of cosine and <c>L2</c> distances;
        ///    codes can be generated from an input via:
        ///    
        ///   <code>
        ///    codebook_size = 50
        ///    codebook_bits = codebook_size * 32
        ///    codebook = tf.get_variable('codebook', [x.shape[-1].value, codebook_bits],
        ///    dtype=x.dtype,
        ///    initializer=tf.orthogonal_initializer())
        ///    codes = compare_and_threshold(tf.matmul(x, codebook), threshold=0.)
        ///    codes = tf.bitcast(codes, tf.int32)  # go from uint8 to int32
        ///    # now codes has shape x.shape[:-1] + [codebook_size]
        ///   </code>
        ///    
        ///    **NOTE**: Currently, the innermost dimension of the tensor must be divisible
        ///    by 8.
        ///    
        ///    Given an <c>input</c> shaped <c>[s0, s1, ..., s_n]</c>, the output is
        ///    a <c>uint8</c> tensor shaped <c>[s0, s1, ..., s_n / 8]</c>.
        /// </remarks>
        public static Tensor compare_and_bitpack (Tensor input, Tensor threshold, string name = "CompareAndBitpack")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["threshold"] = threshold;
            var op = _op_def_lib._apply_op_helper("CompareAndBitpack", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Converts two real numbers to a complex number.
        /// </summary>
        /// <param name="real">
        /// </param>
        /// <param name="imag">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Complex'.
        /// </param>
        /// <param name="Tout">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given a tensor <c>real</c> representing the real part of a complex number, and a
        ///    tensor <c>imag</c> representing the imaginary part of a complex number, this
        ///    operation returns complex numbers elementwise of the form \\(a + bj\\), where
        ///    *a* represents the <c>real</c> part and *b* represents the <c>imag</c> part.
        ///    
        ///    The input tensors <c>real</c> and <c>imag</c> must have the same shape.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # tensor 'real' is [2.25, 3.25]
        ///    # tensor <c>imag</c> is [4.75, 5.75]
        ///    tf.complex(real, imag) ==&amp;gt; [[2.25 + 4.75j], [3.25 + 5.75j]]
        ///   </code>
        /// </remarks>
        public static Tensor complex (Tensor real, Tensor imag, TF_DataType? Tout = null, string name = "Complex")
        {
            var dict = new Dictionary<string, object>();
            dict["real"] = real;
            dict["imag"] = imag;
            if (Tout.HasValue)
                dict["Tout"] = Tout.Value;
            var op = _op_def_lib._apply_op_helper("Complex", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the complex absolute value of a tensor.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ComplexAbs'.
        /// </param>
        /// <param name="Tout">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given a tensor <c>x</c> of complex numbers, this operation returns a tensor of type
        ///    <c>float</c> or <c>double</c> that is the absolute value of each element in <c>x</c>. All
        ///    elements in <c>x</c> must be complex numbers of the form \\(a + bj\\). The absolute
        ///    value is computed as \\( \sqrt{a^2 + b^2}\\).
        /// </remarks>
        public static Tensor complex_abs (Tensor x, TF_DataType? Tout = null, string name = "ComplexAbs")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            if (Tout.HasValue)
                dict["Tout"] = Tout.Value;
            var op = _op_def_lib._apply_op_helper("ComplexAbs", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the ids of the positions in sampled_candidates that match true_labels.
        /// </summary>
        /// <param name="true_classes">
        ///    The true_classes output of UnpackSparseLabels.
        /// </param>
        /// <param name="sampled_candidates">
        ///    The sampled_candidates output of CandidateSampler.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ComputeAccidentalHits'.
        /// </param>
        /// <param name="num_true">
        ///    Optional argument
        ///    Number of true labels per context.
        /// </param>
        /// <param name="seed">
        ///    If either seed or seed2 are set to be non-zero, the random number
        ///    generator is seeded by the given seed.  Otherwise, it is seeded by a
        ///    random seed.
        /// </param>
        /// <param name="seed2">
        ///    An second seed to avoid seed collision.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    indices : A vector of indices corresponding to rows of true_candidates.
        ///    ids : A vector of IDs of positions in sampled_candidates that match a true_label
        ///    for the row with the corresponding index in indices.
        ///    weights : A vector of the same length as indices and ids, in which each element
        ///    is -FLOAT_MAX.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    When doing log-odds NCE, the result of this op should be passed through a
        ///    SparseToDense op, then added to the logits of the sampled candidates. This has
        ///    the effect of 'removing' the sampled labels that match the true labels by
        ///    making the classifier sure that they are sampled labels.
        /// </remarks>
        public static (Tensor indices, Tensor ids, Tensor weights) compute_accidental_hits (Tensor true_classes, Tensor sampled_candidates, int num_true, int? seed = null, int? seed2 = null, string name = "ComputeAccidentalHits")
        {
            var dict = new Dictionary<string, object>();
            dict["true_classes"] = true_classes;
            dict["sampled_candidates"] = sampled_candidates;
            dict["num_true"] = num_true;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("ComputeAccidentalHits", name: name, keywords: dict);
            int _idx = 0;
            var indices = op.outputs[_idx++];
            var ids = op.outputs[_idx++];
            var weights = op.outputs[_idx++];
            return (indices, ids, weights);
        }

        /// <summary>
        ///    Concatenates tensors along one dimension.
        /// </summary>
        /// <param name="concat_dim">
        ///    0-D.  The dimension along which to concatenate.  Must be in the
        ///    range [0, rank(values)).
        /// </param>
        /// <param name="values">
        ///    The <c>N</c> Tensors to concatenate. Their ranks and types must match,
        ///    and their sizes must match in all dimensions except <c>concat_dim</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Concat'.
        /// </param>
        /// <returns>
        ///    A <c>Tensor</c> with the concatenation of values stacked along the
        ///    <c>concat_dim</c> dimension.  This tensor's shape matches that of <c>values</c> except
        ///    in <c>concat_dim</c> where it has the sum of the sizes.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor concat (Tensor concat_dim, Tensor[] values, string name = "Concat")
        {
            var dict = new Dictionary<string, object>();
            dict["concat_dim"] = concat_dim;
            dict["values"] = values;
            var op = _op_def_lib._apply_op_helper("Concat", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes offsets of concat inputs within its output.
        /// </summary>
        /// <param name="concat_dim">
        ///    The dimension along which to concatenate.
        /// </param>
        /// <param name="shape">
        ///    The <c>N</c> int32 vectors representing shape of tensors being concatenated.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ConcatOffset'.
        /// </param>
        /// <returns>
        ///    The <c>N</c> int32 vectors representing the starting offset
        ///    of input tensors within the concatenated output.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    For example:
        ///    
        ///   <code>
        ///    # 'x' is [2, 2, 7]
        ///    # 'y' is [2, 3, 7]
        ///    # 'z' is [2, 5, 7]
        ///    concat_offset(2, [x, y, z]) =&amp;gt; [0, 0, 0], [0, 2, 0], [0, 5, 0]
        ///   </code>
        ///    
        ///    This is typically used by gradient computations for a concat operation.
        /// </remarks>
        public static Tensor[] concat_offset (Tensor concat_dim, Tensor[] shape, string name = "ConcatOffset")
        {
            var dict = new Dictionary<string, object>();
            dict["concat_dim"] = concat_dim;
            dict["shape"] = shape;
            var op = _op_def_lib._apply_op_helper("ConcatOffset", name: name, keywords: dict);
            int _idx = 0;
            var offset = Enumerable.Range(0, op.OutputListLength("offset")).Select(_ => op.outputs[_idx++]).ToArray();
            return (offset);
        }

        /// <summary>
        ///    Concatenates tensors along one dimension.
        /// </summary>
        /// <param name="values">
        ///    List of <c>N</c> Tensors to concatenate. Their ranks and types must match,
        ///    and their sizes must match in all dimensions except <c>concat_dim</c>.
        /// </param>
        /// <param name="axis">
        ///    0-D.  The dimension along which to concatenate.  Must be in the
        ///    range [-rank(values), rank(values)).
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ConcatV2'.
        /// </param>
        /// <returns>
        ///    A <c>Tensor</c> with the concatenation of values stacked along the
        ///    <c>concat_dim</c> dimension.  This tensor's shape matches that of <c>values</c> except
        ///    in <c>concat_dim</c> where it has the sum of the sizes.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor concat_v2 (Tensor[] values, Tensor axis, string name = "ConcatV2")
        {
            var dict = new Dictionary<string, object>();
            dict["values"] = values;
            dict["axis"] = axis;
            var op = _op_def_lib._apply_op_helper("ConcatV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a dataset that concatenates <c>input_dataset</c> with <c>another_dataset</c>.
        /// </summary>
        /// <param name="input_dataset">
        /// </param>
        /// <param name="another_dataset">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ConcatenateDataset'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor concatenate_dataset (Tensor input_dataset, Tensor another_dataset, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "ConcatenateDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["another_dataset"] = another_dataset;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("ConcatenateDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A conditional accumulator for aggregating gradients.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ConditionalAccumulator'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The type of the value being accumulated.
        /// </param>
        /// <param name="shape">
        ///    Optional argument
        ///    The shape of the values, can be [], in which case shape is unknown.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this accumulator is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this accumulator will be shared under the
        ///    given name across multiple sessions.
        /// </param>
        /// <returns>
        ///    The handle to the accumulator.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The accumulator accepts gradients marked with local_step greater or
        ///    equal to the most recent global_step known to the accumulator. The
        ///    average can be extracted from the accumulator, provided sufficient
        ///    gradients have been accumulated. Extracting the average automatically
        ///    resets the aggregate to 0, and increments the global_step recorded by
        ///    the accumulator.
        /// </remarks>
        public static Tensor conditional_accumulator (TF_DataType dtype, TensorShape shape, string container = null, string shared_name = null, string name = "ConditionalAccumulator")
        {
            var dict = new Dictionary<string, object>();
            dict["dtype"] = dtype;
            dict["shape"] = shape;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("ConditionalAccumulator", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    An op that sets up the centralized structures for a distributed TPU
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ConfigureDistributedTPU'.
        /// </param>
        /// <param name="embedding_config">
        ///    Reserved. Do not use.
        /// </param>
        /// <param name="tpu_embedding_config">
        ///    Serialized tensorflow.tpu.TPUEmbeddingConfiguration that
        ///    describes the embedding lookups of the program.
        /// </param>
        /// <param name="is_global_init">
        ///    Reserved. Do not use.
        /// </param>
        /// <returns>
        ///    A serialized tensorflow.tpu.TopologyProto that describes the TPU
        ///    topology.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    system.
        /// </remarks>
        public static Tensor configure_distributed_t_p_u (string embedding_config = null, string tpu_embedding_config = null, bool? is_global_init = null, string name = "ConfigureDistributedTPU")
        {
            var dict = new Dictionary<string, object>();
            if (embedding_config != null)
                dict["embedding_config"] = embedding_config;
            if (tpu_embedding_config != null)
                dict["tpu_embedding_config"] = tpu_embedding_config;
            if (is_global_init.HasValue)
                dict["is_global_init"] = is_global_init.Value;
            var op = _op_def_lib._apply_op_helper("ConfigureDistributedTPU", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the complex conjugate of a complex number.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Conj'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given a tensor <c>input</c> of complex numbers, this operation returns a tensor of
        ///    complex numbers that are the complex conjugate of each element in <c>input</c>. The
        ///    complex numbers in <c>input</c> must be of the form \\(a + bj\\), where *a* is the
        ///    real part and *b* is the imaginary part.
        ///    
        ///    The complex conjugate returned by this operation is of the form \\(a - bj\\).
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # tensor 'input' is [-2.25 + 4.75j, 3.25 + 5.75j]
        ///    tf.conj(input) ==&amp;gt; [-2.25 - 4.75j, 3.25 - 5.75j]
        ///   </code>
        /// </remarks>
        public static Tensor conj (Tensor input, string name = "Conj")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("Conj", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Shuffle dimensions of x according to a permutation and conjugate the result.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="perm">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ConjugateTranspose'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The output <c>y</c> has the same rank as <c>x</c>. The shapes of <c>x</c> and <c>y</c> satisfy:
        ///    <c>y.shape[i] == x.shape[perm[i]] for i in [0, 1, ..., rank(x) - 1]</c>
        ///    <c>y[i,j,k,...,s,t,u] == conj(x[perm[i], perm[j], perm[k],...,perm[s], perm[t], perm[u]])</c>
        /// </remarks>
        public static Tensor conjugate_transpose (Tensor x, Tensor perm, string name = "ConjugateTranspose")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["perm"] = perm;
            var op = _op_def_lib._apply_op_helper("ConjugateTranspose", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns a constant tensor.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Const'.
        /// </param>
        /// <param name="value">
        ///    Optional argument
        ///    Attr <c>value</c> is the tensor to return.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor constant (Tensor value, TF_DataType dtype, string name = "Const")
        {
            var dict = new Dictionary<string, object>();
            dict["value"] = value;
            dict["dtype"] = dtype;
            var op = _op_def_lib._apply_op_helper("Const", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    This op consumes a lock created by <c>MutexLock</c>.
        /// </summary>
        /// <param name="mutex_lock">
        ///    A tensor returned by <c>MutexLock</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ConsumeMutexLock'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    This op exists to consume a tensor created by <c>MutexLock</c> (other than
        ///    direct control dependencies).  It should be the only that consumes the tensor,
        ///    and will raise an error if it is not.  Its only purpose is to keep the
        ///    mutex lock tensor alive until it is consumed by this op.
        ///    
        ///    **NOTE**: This operation must run on the same device as its input.  This may
        ///    be enforced via the <c>colocate_with</c> mechanism.
        /// </remarks>
        public static Operation consume_mutex_lock (Tensor mutex_lock, string name = "ConsumeMutexLock")
        {
            var dict = new Dictionary<string, object>();
            dict["mutex_lock"] = mutex_lock;
            var op = _op_def_lib._apply_op_helper("ConsumeMutexLock", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Does nothing. Serves as a control trigger for scheduling.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ControlTrigger'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    Only useful as a placeholder for control edges.
        /// </remarks>
        public static Operation control_trigger (string name = "ControlTrigger")
        {
            var dict = new Dictionary<string, object>();
            var op = _op_def_lib._apply_op_helper("ControlTrigger", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Computes a 2-D convolution given 4-D <c>input</c> and <c>filter</c> tensors.
        /// </summary>
        /// <param name="input">
        ///    A 4-D tensor. The dimension order is interpreted according to the value
        ///    of <c>data_format</c>, see below for details.
        /// </param>
        /// <param name="filter">
        ///    A 4-D tensor of shape
        ///    <c>[filter_height, filter_width, in_channels, out_channels]</c>
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Conv2D'.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    1-D tensor of length 4.  The stride of the sliding window for each
        ///    dimension of <c>input</c>. The dimension order is determined by the value of
        ///    <c>data_format</c>, see below for details.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="use_cudnn_on_gpu">
        /// </param>
        /// <param name="data_format">
        ///    Specify the data format of the input and output data. With the
        ///    default format "NHWC", the data is stored in the order of:
        ///    [batch, height, width, channels].
        ///    Alternatively, the format could be "NCHW", the data storage order of:
        ///    [batch, channels, height, width].
        /// </param>
        /// <param name="dilations">
        ///    1-D tensor of length 4.  The dilation factor for each dimension of
        ///    <c>input</c>. If set to k &amp;gt; 1, there will be k-1 skipped cells between each
        ///    filter element on that dimension. The dimension order is determined by the
        ///    value of <c>data_format</c>, see above for details. Dilations in the batch and
        ///    depth dimensions must be 1.
        /// </param>
        /// <returns>
        ///    A 4-D tensor. The dimension order is determined by the value of
        ///    <c>data_format</c>, see below for details.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given an input tensor of shape <c>[batch, in_height, in_width, in_channels]</c>
        ///    and a filter / kernel tensor of shape
        ///    <c>[filter_height, filter_width, in_channels, out_channels]</c>, this op
        ///    performs the following:
        ///    
        ///    1. Flattens the filter to a 2-D matrix with shape
        ///    <c>[filter_height * filter_width * in_channels, output_channels]</c>.
        ///    2. Extracts image patches from the input tensor to form a *virtual*
        ///    tensor of shape <c>[batch, out_height, out_width,
        ///    filter_height * filter_width * in_channels]</c>.
        ///    3. For each patch, right-multiplies the filter matrix and the image patch
        ///    vector.
        ///    
        ///    In detail, with the default NHWC format,
        ///    
        ///    output[b, i, j, k] =
        ///    sum_{di, dj, q} input[b, strides[1] * i + di, strides[2] * j + dj, q] *
        ///    filter[di, dj, q, k]
        ///    
        ///    Must have <c>strides[0] = strides[3] = 1</c>.  For the most common case of the same
        ///    horizontal and vertices strides, <c>strides = [1, stride, stride, 1]</c>.
        /// </remarks>
        public static Tensor conv2d (Tensor input, Tensor filter, int[] strides, string padding, bool? use_cudnn_on_gpu = null, string data_format = null, int[] dilations = null, string name = "Conv2D")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["filter"] = filter;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (use_cudnn_on_gpu.HasValue)
                dict["use_cudnn_on_gpu"] = use_cudnn_on_gpu.Value;
            if (data_format != null)
                dict["data_format"] = data_format;
            if (dilations != null)
                dict["dilations"] = dilations;
            var op = _op_def_lib._apply_op_helper("Conv2D", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradients of convolution with respect to the filter.
        /// </summary>
        /// <param name="input">
        ///    4-D with shape <c>[batch, in_height, in_width, in_channels]</c>.
        /// </param>
        /// <param name="filter_sizes">
        ///    An integer vector representing the tensor shape of <c>filter</c>,
        ///    where <c>filter</c> is a 4-D
        ///    <c>[filter_height, filter_width, in_channels, out_channels]</c> tensor.
        /// </param>
        /// <param name="out_backprop">
        ///    4-D with shape <c>[batch, out_height, out_width, out_channels]</c>.
        ///    Gradients w.r.t. the output of the convolution.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Conv2DBackpropFilter'.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    The stride of the sliding window for each dimension of the input
        ///    of the convolution. Must be in the same order as the dimension specified with
        ///    format.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="use_cudnn_on_gpu">
        /// </param>
        /// <param name="data_format">
        ///    Specify the data format of the input and output data. With the
        ///    default format "NHWC", the data is stored in the order of:
        ///    [batch, in_height, in_width, in_channels].
        ///    Alternatively, the format could be "NCHW", the data storage order of:
        ///    [batch, in_channels, in_height, in_width].
        /// </param>
        /// <param name="dilations">
        ///    1-D tensor of length 4.  The dilation factor for each dimension of
        ///    <c>input</c>. If set to k &amp;gt; 1, there will be k-1 skipped cells between each filter
        ///    element on that dimension. The dimension order is determined by the value of
        ///    <c>data_format</c>, see above for details. Dilations in the batch and depth
        ///    dimensions must be 1.
        /// </param>
        /// <returns>
        ///    4-D with shape
        ///    <c>[filter_height, filter_width, in_channels, out_channels]</c>.  Gradient w.r.t.
        ///    the <c>filter</c> input of the convolution.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor conv2d_backprop_filter (Tensor input, Tensor filter_sizes, Tensor out_backprop, int[] strides, string padding, bool? use_cudnn_on_gpu = null, string data_format = null, int[] dilations = null, string name = "Conv2DBackpropFilter")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["filter_sizes"] = filter_sizes;
            dict["out_backprop"] = out_backprop;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (use_cudnn_on_gpu.HasValue)
                dict["use_cudnn_on_gpu"] = use_cudnn_on_gpu.Value;
            if (data_format != null)
                dict["data_format"] = data_format;
            if (dilations != null)
                dict["dilations"] = dilations;
            var op = _op_def_lib._apply_op_helper("Conv2DBackpropFilter", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradients of convolution with respect to the input.
        /// </summary>
        /// <param name="input_sizes">
        ///    An integer vector representing the shape of <c>input</c>,
        ///    where <c>input</c> is a 4-D <c>[batch, height, width, channels]</c> tensor.
        /// </param>
        /// <param name="filter">
        ///    4-D with shape
        ///    <c>[filter_height, filter_width, in_channels, out_channels]</c>.
        /// </param>
        /// <param name="out_backprop">
        ///    4-D with shape <c>[batch, out_height, out_width, out_channels]</c>.
        ///    Gradients w.r.t. the output of the convolution.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Conv2DBackpropInput'.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    The stride of the sliding window for each dimension of the input
        ///    of the convolution. Must be in the same order as the dimension specified with
        ///    format.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="use_cudnn_on_gpu">
        /// </param>
        /// <param name="data_format">
        ///    Specify the data format of the input and output data. With the
        ///    default format "NHWC", the data is stored in the order of:
        ///    [batch, in_height, in_width, in_channels].
        ///    Alternatively, the format could be "NCHW", the data storage order of:
        ///    [batch, in_channels, in_height, in_width].
        /// </param>
        /// <param name="dilations">
        ///    1-D tensor of length 4.  The dilation factor for each dimension of
        ///    <c>input</c>. If set to k &amp;gt; 1, there will be k-1 skipped cells between each filter
        ///    element on that dimension. The dimension order is determined by the value of
        ///    <c>data_format</c>, see above for details. Dilations in the batch and depth
        ///    dimensions must be 1.
        /// </param>
        /// <returns>
        ///    4-D with shape <c>[batch, in_height, in_width, in_channels]</c>.  Gradient
        ///    w.r.t. the input of the convolution.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor conv2d_backprop_input (Tensor input_sizes, Tensor filter, Tensor out_backprop, int[] strides, string padding, bool? use_cudnn_on_gpu = null, string data_format = null, int[] dilations = null, string name = "Conv2DBackpropInput")
        {
            var dict = new Dictionary<string, object>();
            dict["input_sizes"] = input_sizes;
            dict["filter"] = filter;
            dict["out_backprop"] = out_backprop;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (use_cudnn_on_gpu.HasValue)
                dict["use_cudnn_on_gpu"] = use_cudnn_on_gpu.Value;
            if (data_format != null)
                dict["data_format"] = data_format;
            if (dilations != null)
                dict["dilations"] = dilations;
            var op = _op_def_lib._apply_op_helper("Conv2DBackpropInput", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes a 3-D convolution given 5-D <c>input</c> and <c>filter</c> tensors.
        /// </summary>
        /// <param name="input">
        ///    Shape <c>[batch, in_depth, in_height, in_width, in_channels]</c>.
        /// </param>
        /// <param name="filter">
        ///    Shape <c>[filter_depth, filter_height, filter_width, in_channels,
        ///    out_channels]</c>. <c>in_channels</c> must match between <c>input</c> and <c>filter</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Conv3D'.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    1-D tensor of length 5. The stride of the sliding window for each
        ///    dimension of <c>input</c>. Must have <c>strides[0] = strides[4] = 1</c>.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="data_format">
        ///    The data format of the input and output data. With the
        ///    default format "NDHWC", the data is stored in the order of:
        ///    [batch, in_depth, in_height, in_width, in_channels].
        ///    Alternatively, the format could be "NCDHW", the data storage order is:
        ///    [batch, in_channels, in_depth, in_height, in_width].
        /// </param>
        /// <param name="dilations">
        ///    1-D tensor of length 5.  The dilation factor for each dimension of
        ///    <c>input</c>. If set to k &amp;gt; 1, there will be k-1 skipped cells between each
        ///    filter element on that dimension. The dimension order is determined by the
        ///    value of <c>data_format</c>, see above for details. Dilations in the batch and
        ///    depth dimensions must be 1.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    In signal processing, cross-correlation is a measure of similarity of
        ///    two waveforms as a function of a time-lag applied to one of them. This
        ///    is also known as a sliding dot product or sliding inner-product.
        ///    
        ///    Our Conv3D implements a form of cross-correlation.
        /// </remarks>
        public static Tensor conv3d (Tensor input, Tensor filter, int[] strides, string padding, string data_format = null, int[] dilations = null, string name = "Conv3D")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["filter"] = filter;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (data_format != null)
                dict["data_format"] = data_format;
            if (dilations != null)
                dict["dilations"] = dilations;
            var op = _op_def_lib._apply_op_helper("Conv3D", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradients of 3-D convolution with respect to the filter.
        /// </summary>
        /// <param name="input">
        ///    Shape <c>[batch, depth, rows, cols, in_channels]</c>.
        /// </param>
        /// <param name="filter">
        ///    Shape <c>[depth, rows, cols, in_channels, out_channels]</c>.
        ///    <c>in_channels</c> must match between <c>input</c> and <c>filter</c>.
        /// </param>
        /// <param name="out_backprop">
        ///    Backprop signal of shape <c>[batch, out_depth, out_rows, out_cols,
        ///    out_channels]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Conv3DBackpropFilter'.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    1-D tensor of length 5. The stride of the sliding window for each
        ///    dimension of <c>input</c>. Must have <c>strides[0] = strides[4] = 1</c>.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="dilations">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor conv3d_backprop_filter (Tensor input, Tensor filter, Tensor out_backprop, int[] strides, string padding, int[] dilations = null, string name = "Conv3DBackpropFilter")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["filter"] = filter;
            dict["out_backprop"] = out_backprop;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (dilations != null)
                dict["dilations"] = dilations;
            var op = _op_def_lib._apply_op_helper("Conv3DBackpropFilter", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradients of 3-D convolution with respect to the filter.
        /// </summary>
        /// <param name="input">
        ///    Shape <c>[batch, depth, rows, cols, in_channels]</c>.
        /// </param>
        /// <param name="filter_sizes">
        ///    An integer vector representing the tensor shape of <c>filter</c>,
        ///    where <c>filter</c> is a 5-D
        ///    <c>[filter_depth, filter_height, filter_width, in_channels, out_channels]</c>
        ///    tensor.
        /// </param>
        /// <param name="out_backprop">
        ///    Backprop signal of shape <c>[batch, out_depth, out_rows, out_cols,
        ///    out_channels]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Conv3DBackpropFilterV2'.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    1-D tensor of length 5. The stride of the sliding window for each
        ///    dimension of <c>input</c>. Must have <c>strides[0] = strides[4] = 1</c>.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="data_format">
        ///    The data format of the input and output data. With the
        ///    default format "NDHWC", the data is stored in the order of:
        ///    [batch, in_depth, in_height, in_width, in_channels].
        ///    Alternatively, the format could be "NCDHW", the data storage order is:
        ///    [batch, in_channels, in_depth, in_height, in_width].
        /// </param>
        /// <param name="dilations">
        ///    1-D tensor of length 5.  The dilation factor for each dimension of
        ///    <c>input</c>. If set to k &amp;gt; 1, there will be k-1 skipped cells between each
        ///    filter element on that dimension. The dimension order is determined by the
        ///    value of <c>data_format</c>, see above for details. Dilations in the batch and
        ///    depth dimensions must be 1.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor conv3d_backprop_filter_v2 (Tensor input, Tensor filter_sizes, Tensor out_backprop, int[] strides, string padding, string data_format = null, int[] dilations = null, string name = "Conv3DBackpropFilterV2")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["filter_sizes"] = filter_sizes;
            dict["out_backprop"] = out_backprop;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (data_format != null)
                dict["data_format"] = data_format;
            if (dilations != null)
                dict["dilations"] = dilations;
            var op = _op_def_lib._apply_op_helper("Conv3DBackpropFilterV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradients of 3-D convolution with respect to the input.
        /// </summary>
        /// <param name="input">
        ///    Shape <c>[batch, depth, rows, cols, in_channels]</c>.
        /// </param>
        /// <param name="filter">
        ///    Shape <c>[depth, rows, cols, in_channels, out_channels]</c>.
        ///    <c>in_channels</c> must match between <c>input</c> and <c>filter</c>.
        /// </param>
        /// <param name="out_backprop">
        ///    Backprop signal of shape <c>[batch, out_depth, out_rows, out_cols,
        ///    out_channels]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Conv3DBackpropInput'.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    1-D tensor of length 5. The stride of the sliding window for each
        ///    dimension of <c>input</c>. Must have <c>strides[0] = strides[4] = 1</c>.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="dilations">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor conv3d_backprop_input (Tensor input, Tensor filter, Tensor out_backprop, int[] strides, string padding, int[] dilations = null, string name = "Conv3DBackpropInput")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["filter"] = filter;
            dict["out_backprop"] = out_backprop;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (dilations != null)
                dict["dilations"] = dilations;
            var op = _op_def_lib._apply_op_helper("Conv3DBackpropInput", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradients of 3-D convolution with respect to the input.
        /// </summary>
        /// <param name="input_sizes">
        ///    An integer vector representing the tensor shape of <c>input</c>,
        ///    where <c>input</c> is a 5-D
        ///    <c>[batch, depth, rows, cols, in_channels]</c> tensor.
        /// </param>
        /// <param name="filter">
        ///    Shape <c>[depth, rows, cols, in_channels, out_channels]</c>.
        ///    <c>in_channels</c> must match between <c>input</c> and <c>filter</c>.
        /// </param>
        /// <param name="out_backprop">
        ///    Backprop signal of shape <c>[batch, out_depth, out_rows, out_cols,
        ///    out_channels]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Conv3DBackpropInputV2'.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    1-D tensor of length 5. The stride of the sliding window for each
        ///    dimension of <c>input</c>. Must have <c>strides[0] = strides[4] = 1</c>.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="data_format">
        ///    The data format of the input and output data. With the
        ///    default format "NDHWC", the data is stored in the order of:
        ///    [batch, in_depth, in_height, in_width, in_channels].
        ///    Alternatively, the format could be "NCDHW", the data storage order is:
        ///    [batch, in_channels, in_depth, in_height, in_width].
        /// </param>
        /// <param name="dilations">
        ///    1-D tensor of length 5.  The dilation factor for each dimension of
        ///    <c>input</c>. If set to k &amp;gt; 1, there will be k-1 skipped cells between each
        ///    filter element on that dimension. The dimension order is determined by the
        ///    value of <c>data_format</c>, see above for details. Dilations in the batch and
        ///    depth dimensions must be 1.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor conv3d_backprop_input_v2 (Tensor input_sizes, Tensor filter, Tensor out_backprop, int[] strides, string padding, string data_format = null, int[] dilations = null, string name = "Conv3DBackpropInputV2")
        {
            var dict = new Dictionary<string, object>();
            dict["input_sizes"] = input_sizes;
            dict["filter"] = filter;
            dict["out_backprop"] = out_backprop;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (data_format != null)
                dict["data_format"] = data_format;
            if (dilations != null)
                dict["dilations"] = dilations;
            var op = _op_def_lib._apply_op_helper("Conv3DBackpropInputV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Copy Op.
        /// </summary>
        /// <param name="input">
        ///    Input tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Copy'.
        /// </param>
        /// <param name="tensor_name">
        ///    The name of the input tensor.
        /// </param>
        /// <param name="debug_ops_spec">
        ///    A list of debug op spec (op, url, gated_grpc) for attached debug
        ///    ops. Each element of the list has the format
        ///    &amp;lt;debug_op&amp;gt;;&amp;lt;grpc_url&amp;gt;;&amp;lt;gated_grpc&amp;gt;, wherein gated_grpc is boolean represented
        ///    as 0/1. E.g., "DebugIdentity;grpc://foo:3333;1",
        ///    "DebugIdentity;file:///tmp/tfdbg_1;0".
        /// </param>
        /// <returns>
        ///    Output tensor, deep-copied from input.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Performs CPU-to-CPU or GPU-to-GPU deep-copying of tensor, depending on the
        ///    device on which the tensor is allocated.
        ///    N.B.: If the all downstream attached debug ops are disabled given the current
        ///    gRPC gating status, the output will simply forward the input tensor without
        ///    deep-copying. See the documentation of Debug* ops for more details.
        ///    
        ///    Unlike the CopyHost Op, this op does not have HostMemory constraint on its
        ///    input or output.
        /// </remarks>
        public static Tensor copy (Tensor input, string tensor_name = null, string[] debug_ops_spec = null, string name = "Copy")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (tensor_name != null)
                dict["tensor_name"] = tensor_name;
            if (debug_ops_spec != null)
                dict["debug_ops_spec"] = debug_ops_spec;
            var op = _op_def_lib._apply_op_helper("Copy", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Copy Host Op.
        /// </summary>
        /// <param name="input">
        ///    Input tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CopyHost'.
        /// </param>
        /// <param name="tensor_name">
        ///    The name of the input tensor.
        /// </param>
        /// <param name="debug_ops_spec">
        ///    A list of debug op spec (op, url, gated_grpc) for attached debug
        ///    ops. Each element of the list has the format
        ///    &amp;lt;debug_op&amp;gt;;&amp;lt;grpc_url&amp;gt;;&amp;lt;gated_grpc&amp;gt;, wherein gated_grpc is boolean represented
        ///    as 0/1. E.g., "DebugIdentity;grpc://foo:3333;1",
        ///    "DebugIdentity;file:///tmp/tfdbg_1;0".
        /// </param>
        /// <returns>
        ///    Output tensor, deep-copied from input.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Performs CPU-to-CPU deep-copying of tensor.
        ///    N.B.: If the all downstream attached debug ops are disabled given the current
        ///    gRPC gating status, the output will simply forward the input tensor without
        ///    deep-copying. See the documentation of Debug* ops for more details.
        ///    
        ///    Unlike the Copy Op, this op has HostMemory constraint on its input or output.
        /// </remarks>
        public static Tensor copy_host (Tensor input, string tensor_name = null, string[] debug_ops_spec = null, string name = "CopyHost")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (tensor_name != null)
                dict["tensor_name"] = tensor_name;
            if (debug_ops_spec != null)
                dict["debug_ops_spec"] = debug_ops_spec;
            var op = _op_def_lib._apply_op_helper("CopyHost", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes cos of x element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Cos'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor cos (Tensor x, string name = "Cos")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Cos", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes hyperbolic cosine of x element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Cosh'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor cosh (Tensor x, string name = "Cosh")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Cosh", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Increments 'ref' until it reaches 'limit'.
        /// </summary>
        /// <param name="referecne">
        ///    Should be from a scalar <c>Variable</c> node.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CountUpTo'.
        /// </param>
        /// <param name="limit">
        ///    Optional argument
        ///    If incrementing ref would bring it above limit, instead generates an
        ///    'OutOfRange' error.
        /// </param>
        /// <returns>
        ///    A copy of the input before increment. If nothing else modifies the
        ///    input, the values produced will all be distinct.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor count_up_to (Tensor referecne, int limit, string name = "CountUpTo")
        {
            var dict = new Dictionary<string, object>();
            dict["ref"] = referecne;
            dict["limit"] = limit;
            var op = _op_def_lib._apply_op_helper("CountUpTo", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Extracts crops from the input image tensor and resizes them.
        /// </summary>
        /// <param name="image">
        ///    A 4-D tensor of shape <c>[batch, image_height, image_width, depth]</c>.
        ///    Both <c>image_height</c> and <c>image_width</c> need to be positive.
        /// </param>
        /// <param name="boxes">
        ///    A 2-D tensor of shape <c>[num_boxes, 4]</c>. The <c>i</c>-th row of the tensor
        ///    specifies the coordinates of a box in the <c>box_ind[i]</c> image and is specified
        ///    in normalized coordinates <c>[y1, x1, y2, x2]</c>. A normalized coordinate value of
        ///    <c>y</c> is mapped to the image coordinate at <c>y * (image_height - 1)</c>, so as the
        ///    <c>[0, 1]</c> interval of normalized image height is mapped to
        ///    <c>[0, image_height - 1]</c> in image height coordinates. We do allow <c>y1</c> &amp;gt; <c>y2</c>, in
        ///    which case the sampled crop is an up-down flipped version of the original
        ///    image. The width dimension is treated similarly. Normalized coordinates
        ///    outside the <c>[0, 1]</c> range are allowed, in which case we use
        ///    <c>extrapolation_value</c> to extrapolate the input image values.
        /// </param>
        /// <param name="box_ind">
        ///    A 1-D tensor of shape <c>[num_boxes]</c> with int32 values in <c>[0, batch)</c>.
        ///    The value of <c>box_ind[i]</c> specifies the image that the <c>i</c>-th box refers to.
        /// </param>
        /// <param name="crop_size">
        ///    A 1-D tensor of 2 elements, <c>size = [crop_height, crop_width]</c>. All
        ///    cropped image patches are resized to this size. The aspect ratio of the image
        ///    content is not preserved. Both <c>crop_height</c> and <c>crop_width</c> need to be
        ///    positive.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CropAndResize'.
        /// </param>
        /// <param name="method">
        ///    A string specifying the sampling method for resizing. It can be either
        ///    <c>"bilinear"</c> or <c>"nearest"</c> and default to <c>"bilinear"</c>. Currently two sampling
        ///    methods are supported: Bilinear and Nearest Neighbor.
        /// </param>
        /// <param name="extrapolation_value">
        ///    Value used for extrapolation, when applicable.
        /// </param>
        /// <returns>
        ///    A 4-D tensor of shape <c>[num_boxes, crop_height, crop_width, depth]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Extracts crops from the input image tensor and resizes them using bilinear
        ///    sampling or nearest neighbor sampling (possibly with aspect ratio change) to a
        ///    common output size specified by <c>crop_size</c>. This is more general than the
        ///    <c>crop_to_bounding_box</c> op which extracts a fixed size slice from the input image
        ///    and does not allow resizing or aspect ratio change.
        ///    
        ///    Returns a tensor with <c>crops</c> from the input <c>image</c> at positions defined at the
        ///    bounding box locations in <c>boxes</c>. The cropped boxes are all resized (with
        ///    bilinear or nearest neighbor interpolation) to a fixed
        ///    <c>size = [crop_height, crop_width]</c>. The result is a 4-D tensor
        ///    <c>[num_boxes, crop_height, crop_width, depth]</c>. The resizing is corner aligned.
        ///    In particular, if <c>boxes = [[0, 0, 1, 1]]</c>, the method will give identical
        ///    results to using <c>tf.image.resize_bilinear()</c> or
        ///    <c>tf.image.resize_nearest_neighbor()</c>(depends on the <c>method</c> argument) with
        ///    <c>align_corners=True</c>.
        /// </remarks>
        public static Tensor crop_and_resize (Tensor image, Tensor boxes, Tensor box_ind, Tensor crop_size, string method = null, float? extrapolation_value = null, string name = "CropAndResize")
        {
            var dict = new Dictionary<string, object>();
            dict["image"] = image;
            dict["boxes"] = boxes;
            dict["box_ind"] = box_ind;
            dict["crop_size"] = crop_size;
            if (method != null)
                dict["method"] = method;
            if (extrapolation_value.HasValue)
                dict["extrapolation_value"] = extrapolation_value.Value;
            var op = _op_def_lib._apply_op_helper("CropAndResize", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradient of the crop_and_resize op wrt the input boxes tensor.
        /// </summary>
        /// <param name="grads">
        ///    A 4-D tensor of shape <c>[num_boxes, crop_height, crop_width, depth]</c>.
        /// </param>
        /// <param name="image">
        ///    A 4-D tensor of shape <c>[batch, image_height, image_width, depth]</c>.
        ///    Both <c>image_height</c> and <c>image_width</c> need to be positive.
        /// </param>
        /// <param name="boxes">
        ///    A 2-D tensor of shape <c>[num_boxes, 4]</c>. The <c>i</c>-th row of the tensor
        ///    specifies the coordinates of a box in the <c>box_ind[i]</c> image and is specified
        ///    in normalized coordinates <c>[y1, x1, y2, x2]</c>. A normalized coordinate value of
        ///    <c>y</c> is mapped to the image coordinate at <c>y * (image_height - 1)</c>, so as the
        ///    <c>[0, 1]</c> interval of normalized image height is mapped to
        ///    <c>[0, image_height - 1] in image height coordinates. We do allow y1 &amp;gt; y2, in
        ///    which case the sampled crop is an up-down flipped version of the original
        ///    image. The width dimension is treated similarly. Normalized coordinates
        ///    outside the </c>[0, 1]<c> range are allowed, in which case we use
        ///    </c>extrapolation_value<c> to extrapolate the input image values.
        /// </param>
        /// <param name="box_ind">
        ///    A 1-D tensor of shape <c>[num_boxes]</c> with int32 values in <c>[0, batch)</c>.
        ///    The value of <c>box_ind[i]</c> specifies the image that the <c>i</c>-th box refers to.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CropAndResizeGradBoxes'.
        /// </param>
        /// <param name="method">
        ///    A string specifying the interpolation method. Only 'bilinear' is
        ///    supported for now.
        /// </param>
        /// <returns>
        ///    A 2-D tensor of shape <c>[num_boxes, 4]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor crop_and_resize_grad_boxes (Tensor grads, Tensor image, Tensor boxes, Tensor box_ind, string method = null, string name = "CropAndResizeGradBoxes")
        {
            var dict = new Dictionary<string, object>();
            dict["grads"] = grads;
            dict["image"] = image;
            dict["boxes"] = boxes;
            dict["box_ind"] = box_ind;
            if (method != null)
                dict["method"] = method;
            var op = _op_def_lib._apply_op_helper("CropAndResizeGradBoxes", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradient of the crop_and_resize op wrt the input image tensor.
        /// </summary>
        /// <param name="grads">
        ///    A 4-D tensor of shape <c>[num_boxes, crop_height, crop_width, depth]</c>.
        /// </param>
        /// <param name="boxes">
        ///    A 2-D tensor of shape <c>[num_boxes, 4]</c>. The <c>i</c>-th row of the tensor
        ///    specifies the coordinates of a box in the <c>box_ind[i]</c> image and is specified
        ///    in normalized coordinates <c>[y1, x1, y2, x2]</c>. A normalized coordinate value of
        ///    <c>y</c> is mapped to the image coordinate at <c>y * (image_height - 1)</c>, so as the
        ///    <c>[0, 1]</c> interval of normalized image height is mapped to
        ///    <c>[0, image_height - 1] in image height coordinates. We do allow y1 &amp;gt; y2, in
        ///    which case the sampled crop is an up-down flipped version of the original
        ///    image. The width dimension is treated similarly. Normalized coordinates
        ///    outside the </c>[0, 1]<c> range are allowed, in which case we use
        ///    </c>extrapolation_value<c> to extrapolate the input image values.
        /// </param>
        /// <param name="box_ind">
        ///    A 1-D tensor of shape <c>[num_boxes]</c> with int32 values in <c>[0, batch)</c>.
        ///    The value of <c>box_ind[i]</c> specifies the image that the <c>i</c>-th box refers to.
        /// </param>
        /// <param name="image_size">
        ///    A 1-D tensor with value <c>[batch, image_height, image_width, depth]</c>
        ///    containing the original image size. Both <c>image_height</c> and <c>image_width</c> need
        ///    to be positive.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CropAndResizeGradImage'.
        /// </param>
        /// <param name="T">
        ///    Optional argument
        /// </param>
        /// <param name="method">
        ///    A string specifying the interpolation method. Only 'bilinear' is
        ///    supported for now.
        /// </param>
        /// <returns>
        ///    A 4-D tensor of shape <c>[batch, image_height, image_width, depth]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor crop_and_resize_grad_image (Tensor grads, Tensor boxes, Tensor box_ind, Tensor image_size, TF_DataType T, string method = null, string name = "CropAndResizeGradImage")
        {
            var dict = new Dictionary<string, object>();
            dict["grads"] = grads;
            dict["boxes"] = boxes;
            dict["box_ind"] = box_ind;
            dict["image_size"] = image_size;
            dict["T"] = T;
            if (method != null)
                dict["method"] = method;
            var op = _op_def_lib._apply_op_helper("CropAndResizeGradImage", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Compute the pairwise cross product.
        /// </summary>
        /// <param name="a">
        ///    A tensor containing 3-element vectors.
        /// </param>
        /// <param name="b">
        ///    Another tensor, of same type and shape as <c>a</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Cross'.
        /// </param>
        /// <returns>
        ///    Pairwise cross product of the vectors in <c>a</c> and <c>b</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    <c>a</c> and <c>b</c> must be the same shape; they can either be simple 3-element vectors,
        ///    or any shape where the innermost dimension is 3. In the latter case, each pair
        ///    of corresponding 3-element vectors is cross-multiplied independently.
        /// </remarks>
        public static Tensor cross (Tensor a, Tensor b, string name = "Cross")
        {
            var dict = new Dictionary<string, object>();
            dict["a"] = a;
            dict["b"] = b;
            var op = _op_def_lib._apply_op_helper("Cross", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    An Op to sum inputs across replicated TPU instances. Each
        /// </summary>
        /// <param name="input">
        ///    The local input to the sum.
        /// </param>
        /// <param name="group_assignment">
        ///    An int32 tensor with shape
        ///    [num_groups, num_replicas_per_group]. <c>group_assignment[i]</c> represents the
        ///    replica ids in the ith subgroup.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CrossReplicaSum'.
        /// </param>
        /// <returns>
        ///    The sum of all the distributed inputs.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    instance supplies its own input. If group_assignment is empty, the output of
        ///    each is the sum of all the inputs, otherwise the output of each is the sum of
        ///    the inputs belonging to the same group.
        ///    
        ///    For example, suppose there are 8 TPU instances: <c>[A, B, C, D, E, F, G, H]</c>.
        ///    Passing group_assignment=<c>[[0,2,4,6],[1,3,5,7]]</c> sets <c>A, C, E, G</c> as group 0,
        ///    and <c>B, D, F, H</c> as group 1. Thus we get the outputs:
        ///    <c>[A+C+E+G, B+D+F+H, A+C+E+G, B+D+F+H, A+C+E+G, B+D+F+H, A+C+E+G, B+D+F+H]</c>.
        /// </remarks>
        public static Tensor cross_replica_sum (Tensor input, Tensor group_assignment, string name = "CrossReplicaSum")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["group_assignment"] = group_assignment;
            var op = _op_def_lib._apply_op_helper("CrossReplicaSum", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A RNN backed by cuDNN.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="input_h">
        /// </param>
        /// <param name="input_c">
        /// </param>
        /// <param name="parameters">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CudnnRNN'.
        /// </param>
        /// <param name="rnn_mode">
        /// </param>
        /// <param name="input_mode">
        /// </param>
        /// <param name="direction">
        /// </param>
        /// <param name="dropout">
        /// </param>
        /// <param name="seed">
        /// </param>
        /// <param name="seed2">
        /// </param>
        /// <param name="is_training">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output :
        ///    output_h :
        ///    output_c :
        ///    reserve_space :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Computes the RNN from the input and initial states, with respect to the params
        ///    buffer.
        ///    
        ///    rnn_mode: Indicates the type of the RNN model.
        ///    input_mode: Indicate whether there is a linear projection between the input and
        ///    the actual computation before the first layer. 'skip_input' is only allowed
        ///    when input_size == num_units; 'auto_select' implies 'skip_input' when
        ///    input_size == num_units; otherwise, it implies 'linear_input'.
        ///    direction: Indicates whether a bidirectional model will be used. Should be
        ///    "unidirectional" or "bidirectional".
        ///    dropout: Dropout probability. When set to 0., dropout is disabled.
        ///    seed: The 1st part of a seed to initialize dropout.
        ///    seed2: The 2nd part of a seed to initialize dropout.
        ///    input: A 3-D tensor with the shape of [seq_length, batch_size, input_size].
        ///    input_h: A 3-D tensor with the shape of [num_layer * dir, batch_size,
        ///    num_units].
        ///    input_c: For LSTM, a 3-D tensor with the shape of
        ///    [num_layer * dir, batch, num_units]. For other models, it is ignored.
        ///    params: A 1-D tensor that contains the weights and biases in an opaque layout.
        ///    The size must be created through CudnnRNNParamsSize, and initialized
        ///    separately. Note that they might not be compatible across different
        ///    generations. So it is a good idea to save and restore
        ///    output: A 3-D tensor with the shape of [seq_length, batch_size,
        ///    dir * num_units].
        ///    output_h: The same shape has input_h.
        ///    output_c: The same shape as input_c for LSTM. An empty tensor for other models.
        ///    is_training: Indicates whether this operation is used for inferenece or
        ///    training.
        ///    reserve_space: An opaque tensor that can be used in backprop calculation. It
        ///    is only produced if is_training is false.
        /// </remarks>
        public static (Tensor output, Tensor output_h, Tensor output_c, Tensor reserve_space) cudnn_r_n_n (Tensor input, Tensor input_h, Tensor input_c, Tensor parameters, string rnn_mode = null, string input_mode = null, string direction = null, float? dropout = null, int? seed = null, int? seed2 = null, bool? is_training = null, string name = "CudnnRNN")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["input_h"] = input_h;
            dict["input_c"] = input_c;
            dict["params"] = parameters;
            if (rnn_mode != null)
                dict["rnn_mode"] = rnn_mode;
            if (input_mode != null)
                dict["input_mode"] = input_mode;
            if (direction != null)
                dict["direction"] = direction;
            if (dropout.HasValue)
                dict["dropout"] = dropout.Value;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            if (is_training.HasValue)
                dict["is_training"] = is_training.Value;
            var op = _op_def_lib._apply_op_helper("CudnnRNN", name: name, keywords: dict);
            int _idx = 0;
            var output = op.outputs[_idx++];
            var output_h = op.outputs[_idx++];
            var output_c = op.outputs[_idx++];
            var reserve_space = op.outputs[_idx++];
            return (output, output_h, output_c, reserve_space);
        }

        /// <summary>
        ///    Backprop step of CudnnRNN.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="input_h">
        /// </param>
        /// <param name="input_c">
        /// </param>
        /// <param name="parameters">
        /// </param>
        /// <param name="output">
        /// </param>
        /// <param name="output_h">
        /// </param>
        /// <param name="output_c">
        /// </param>
        /// <param name="output_backprop">
        /// </param>
        /// <param name="output_h_backprop">
        /// </param>
        /// <param name="output_c_backprop">
        /// </param>
        /// <param name="reserve_space">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CudnnRNNBackprop'.
        /// </param>
        /// <param name="rnn_mode">
        /// </param>
        /// <param name="input_mode">
        /// </param>
        /// <param name="direction">
        /// </param>
        /// <param name="dropout">
        /// </param>
        /// <param name="seed">
        /// </param>
        /// <param name="seed2">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    input_backprop :
        ///    input_h_backprop :
        ///    input_c_backprop :
        ///    params_backprop :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Compute the backprop of both data and weights in a RNN.
        ///    
        ///    rnn_mode: Indicates the type of the RNN model.
        ///    input_mode: Indicate whether there is a linear projection between the input and
        ///    the actual computation before the first layer. 'skip_input' is only allowed
        ///    when input_size == num_units; 'auto_select' implies 'skip_input' when
        ///    input_size == num_units; otherwise, it implies 'linear_input'.
        ///    direction: Indicates whether a bidirectional model will be used. Should be
        ///    "unidirectional" or "bidirectional".
        ///    dropout: Dropout probability. When set to 0., dropout is disabled.
        ///    seed: The 1st part of a seed to initialize dropout.
        ///    seed2: The 2nd part of a seed to initialize dropout.
        ///    input: A 3-D tensor with the shape of [seq_length, batch_size, input_size].
        ///    input_h: A 3-D tensor with the shape of [num_layer * dir, batch_size,
        ///    num_units].
        ///    input_c: For LSTM, a 3-D tensor with the shape of
        ///    [num_layer * dir, batch, num_units]. For other models, it is ignored.
        ///    params: A 1-D tensor that contains the weights and biases in an opaque layout.
        ///    The size must be created through CudnnRNNParamsSize, and initialized
        ///    separately. Note that they might not be compatible across different
        ///    generations. So it is a good idea to save and restore
        ///    output: A 3-D tensor with the shape of [seq_length, batch_size,
        ///    dir * num_units].
        ///    output_h: The same shape has input_h.
        ///    output_c: The same shape as input_c for LSTM. An empty tensor for other models.
        ///    output_backprop: A 3-D tensor with the same shape as output in the forward pass.
        ///    output_h_backprop: A 3-D tensor with the same shape as output_h in the forward
        ///    pass.
        ///    output_c_backprop: A 3-D tensor with the same shape as output_c in the forward
        ///    pass.
        ///    reserve_space: The same reserve_space produced in for forward operation.
        ///    input_backprop: The backprop to input in the forward pass. Has the same shape
        ///    as input.
        ///    input_h_backprop: The backprop to input_h in the forward pass. Has the same
        ///    shape as input_h.
        ///    input_c_backprop: The backprop to input_c in the forward pass. Has the same
        ///    shape as input_c.
        ///    params_backprop: The backprop to the params buffer in the forward pass. Has the
        ///    same shape as params.
        /// </remarks>
        public static (Tensor input_backprop, Tensor input_h_backprop, Tensor input_c_backprop, Tensor params_backprop) cudnn_r_n_n_backprop (Tensor input, Tensor input_h, Tensor input_c, Tensor parameters, Tensor output, Tensor output_h, Tensor output_c, Tensor output_backprop, Tensor output_h_backprop, Tensor output_c_backprop, Tensor reserve_space, string rnn_mode = null, string input_mode = null, string direction = null, float? dropout = null, int? seed = null, int? seed2 = null, string name = "CudnnRNNBackprop")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["input_h"] = input_h;
            dict["input_c"] = input_c;
            dict["params"] = parameters;
            dict["output"] = output;
            dict["output_h"] = output_h;
            dict["output_c"] = output_c;
            dict["output_backprop"] = output_backprop;
            dict["output_h_backprop"] = output_h_backprop;
            dict["output_c_backprop"] = output_c_backprop;
            dict["reserve_space"] = reserve_space;
            if (rnn_mode != null)
                dict["rnn_mode"] = rnn_mode;
            if (input_mode != null)
                dict["input_mode"] = input_mode;
            if (direction != null)
                dict["direction"] = direction;
            if (dropout.HasValue)
                dict["dropout"] = dropout.Value;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("CudnnRNNBackprop", name: name, keywords: dict);
            int _idx = 0;
            var input_backprop = op.outputs[_idx++];
            var input_h_backprop = op.outputs[_idx++];
            var input_c_backprop = op.outputs[_idx++];
            var params_backprop = op.outputs[_idx++];
            return (input_backprop, input_h_backprop, input_c_backprop, params_backprop);
        }

        /// <summary>
        ///    Backprop step of CudnnRNN.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="input_h">
        /// </param>
        /// <param name="input_c">
        /// </param>
        /// <param name="parameters">
        /// </param>
        /// <param name="output">
        /// </param>
        /// <param name="output_h">
        /// </param>
        /// <param name="output_c">
        /// </param>
        /// <param name="output_backprop">
        /// </param>
        /// <param name="output_h_backprop">
        /// </param>
        /// <param name="output_c_backprop">
        /// </param>
        /// <param name="reserve_space">
        /// </param>
        /// <param name="host_reserved">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CudnnRNNBackpropV2'.
        /// </param>
        /// <param name="rnn_mode">
        /// </param>
        /// <param name="input_mode">
        /// </param>
        /// <param name="direction">
        /// </param>
        /// <param name="dropout">
        /// </param>
        /// <param name="seed">
        /// </param>
        /// <param name="seed2">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    input_backprop :
        ///    input_h_backprop :
        ///    input_c_backprop :
        ///    params_backprop :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Compute the backprop of both data and weights in a RNN. Takes an extra
        ///    "host_reserved" inupt than CudnnRNNBackprop, which is used to determine RNN
        ///    cudnnRNNAlgo_t and cudnnMathType_t.
        ///    
        ///    rnn_mode: Indicates the type of the RNN model.
        ///    input_mode: Indicates whether there is a linear projection between the input and
        ///    the actual computation before the first layer. 'skip_input' is only allowed
        ///    when input_size == num_units; 'auto_select' implies 'skip_input' when
        ///    input_size == num_units; otherwise, it implies 'linear_input'.
        ///    direction: Indicates whether a bidirectional model will be used. Should be
        ///    "unidirectional" or "bidirectional".
        ///    dropout: Dropout probability. When set to 0., dropout is disabled.
        ///    seed: The 1st part of a seed to initialize dropout.
        ///    seed2: The 2nd part of a seed to initialize dropout.
        ///    input: A 3-D tensor with the shape of [seq_length, batch_size, input_size].
        ///    input_h: A 3-D tensor with the shape of [num_layer * dir, batch_size,
        ///    num_units].
        ///    input_c: For LSTM, a 3-D tensor with the shape of
        ///    [num_layer * dir, batch, num_units]. For other models, it is ignored.
        ///    params: A 1-D tensor that contains the weights and biases in an opaque layout.
        ///    The size must be created through CudnnRNNParamsSize, and initialized
        ///    separately. Note that they might not be compatible across different
        ///    generations. So it is a good idea to save and restore
        ///    output: A 3-D tensor with the shape of [seq_length, batch_size,
        ///    dir * num_units].
        ///    output_h: The same shape has input_h.
        ///    output_c: The same shape as input_c for LSTM. An empty tensor for other models.
        ///    output_backprop: A 3-D tensor with the same shape as output in the forward pass.
        ///    output_h_backprop: A 3-D tensor with the same shape as output_h in the forward
        ///    pass.
        ///    output_c_backprop: A 3-D tensor with the same shape as output_c in the forward
        ///    pass.
        ///    reserve_space: The same reserve_space produced in the forward operation.
        ///    host_reserved: The same host_reserved produced in the forward operation.
        ///    input_backprop: The backprop to input in the forward pass. Has the same shape
        ///    as input.
        ///    input_h_backprop: The backprop to input_h in the forward pass. Has the same
        ///    shape as input_h.
        ///    input_c_backprop: The backprop to input_c in the forward pass. Has the same
        ///    shape as input_c.
        ///    params_backprop: The backprop to the params buffer in the forward pass. Has the
        ///    same shape as params.
        /// </remarks>
        public static (Tensor input_backprop, Tensor input_h_backprop, Tensor input_c_backprop, Tensor params_backprop) cudnn_r_n_n_backprop_v2 (Tensor input, Tensor input_h, Tensor input_c, Tensor parameters, Tensor output, Tensor output_h, Tensor output_c, Tensor output_backprop, Tensor output_h_backprop, Tensor output_c_backprop, Tensor reserve_space, Tensor host_reserved, string rnn_mode = null, string input_mode = null, string direction = null, float? dropout = null, int? seed = null, int? seed2 = null, string name = "CudnnRNNBackpropV2")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["input_h"] = input_h;
            dict["input_c"] = input_c;
            dict["params"] = parameters;
            dict["output"] = output;
            dict["output_h"] = output_h;
            dict["output_c"] = output_c;
            dict["output_backprop"] = output_backprop;
            dict["output_h_backprop"] = output_h_backprop;
            dict["output_c_backprop"] = output_c_backprop;
            dict["reserve_space"] = reserve_space;
            dict["host_reserved"] = host_reserved;
            if (rnn_mode != null)
                dict["rnn_mode"] = rnn_mode;
            if (input_mode != null)
                dict["input_mode"] = input_mode;
            if (direction != null)
                dict["direction"] = direction;
            if (dropout.HasValue)
                dict["dropout"] = dropout.Value;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("CudnnRNNBackpropV2", name: name, keywords: dict);
            int _idx = 0;
            var input_backprop = op.outputs[_idx++];
            var input_h_backprop = op.outputs[_idx++];
            var input_c_backprop = op.outputs[_idx++];
            var params_backprop = op.outputs[_idx++];
            return (input_backprop, input_h_backprop, input_c_backprop, params_backprop);
        }

        /// <summary>
        ///    Converts CudnnRNN params from canonical form to usable form.
        /// </summary>
        /// <param name="num_layers">
        /// </param>
        /// <param name="num_units">
        /// </param>
        /// <param name="input_size">
        /// </param>
        /// <param name="weights">
        /// </param>
        /// <param name="biases">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CudnnRNNCanonicalToParams'.
        /// </param>
        /// <param name="rnn_mode">
        /// </param>
        /// <param name="input_mode">
        /// </param>
        /// <param name="direction">
        /// </param>
        /// <param name="dropout">
        /// </param>
        /// <param name="seed">
        /// </param>
        /// <param name="seed2">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Writes a set of weights into the opaque params buffer so they can be used in
        ///    upcoming training or inferences.
        ///    
        ///    Note that the params buffer may not be compatible across different GPUs. So any
        ///    save and restoration should be converted to and from the canonical weights and
        ///    biases.
        ///    
        ///    num_layers: Specifies the number of layers in the RNN model.
        ///    num_units: Specifies the size of the hidden state.
        ///    input_size: Specifies the size of the input state.
        ///    weights: the canonical form of weights that can be used for saving
        ///    and restoration. They are more likely to be compatible across different
        ///    generations.
        ///    biases: the canonical form of biases that can be used for saving
        ///    and restoration. They are more likely to be compatible across different
        ///    generations.
        ///    num_params: number of parameter sets for all layers.
        ///    Each layer may contain multiple parameter sets, with each set consisting of
        ///    a weight matrix and a bias vector.
        ///    rnn_mode: Indicates the type of the RNN model.
        ///    input_mode: Indicate whether there is a linear projection between the input and
        ///    The actual computation before the first layer. 'skip_input' is only allowed
        ///    when input_size == num_units; 'auto_select' implies 'skip_input' when
        ///    input_size == num_units; otherwise, it implies 'linear_input'.
        ///    direction: Indicates whether a bidirectional model will be used.
        ///    dir = (direction == bidirectional) ? 2 : 1
        ///    dropout: dropout probability. When set to 0., dropout is disabled.
        ///    seed: the 1st part of a seed to initialize dropout.
        ///    seed2: the 2nd part of a seed to initialize dropout.
        /// </remarks>
        public static Tensor cudnn_r_n_n_canonical_to_params (Tensor num_layers, Tensor num_units, Tensor input_size, Tensor[] weights, Tensor[] biases, string rnn_mode = null, string input_mode = null, string direction = null, float? dropout = null, int? seed = null, int? seed2 = null, string name = "CudnnRNNCanonicalToParams")
        {
            var dict = new Dictionary<string, object>();
            dict["num_layers"] = num_layers;
            dict["num_units"] = num_units;
            dict["input_size"] = input_size;
            dict["weights"] = weights;
            dict["biases"] = biases;
            if (rnn_mode != null)
                dict["rnn_mode"] = rnn_mode;
            if (input_mode != null)
                dict["input_mode"] = input_mode;
            if (direction != null)
                dict["direction"] = direction;
            if (dropout.HasValue)
                dict["dropout"] = dropout.Value;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("CudnnRNNCanonicalToParams", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes size of weights that can be used by a Cudnn RNN model.
        /// </summary>
        /// <param name="num_layers">
        /// </param>
        /// <param name="num_units">
        /// </param>
        /// <param name="input_size">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CudnnRNNParamsSize'.
        /// </param>
        /// <param name="T">
        ///    Optional argument
        /// </param>
        /// <param name="S">
        ///    Optional argument
        /// </param>
        /// <param name="rnn_mode">
        /// </param>
        /// <param name="input_mode">
        /// </param>
        /// <param name="direction">
        /// </param>
        /// <param name="dropout">
        /// </param>
        /// <param name="seed">
        /// </param>
        /// <param name="seed2">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Return the params size that can be used by the Cudnn RNN model. Subsequent
        ///    weight allocation and initialization should use this size.
        ///    
        ///    num_layers: Specifies the number of layers in the RNN model.
        ///    num_units: Specifies the size of the hidden state.
        ///    input_size: Specifies the size of the input state.
        ///    rnn_mode: Indicates the type of the RNN model.
        ///    input_mode: Indicate whether there is a linear projection between the input and
        ///    The actual computation before the first layer. 'skip_input' is only allowed
        ///    when input_size == num_units; 'auto_select' implies 'skip_input' when
        ///    input_size == num_units; otherwise, it implies 'linear_input'.
        ///    direction: Indicates whether a bidirectional model will be used.
        ///    dir = (direction == bidirectional) ? 2 : 1
        ///    dropout: dropout probability. When set to 0., dropout is disabled.
        ///    seed: the 1st part of a seed to initialize dropout.
        ///    seed2: the 2nd part of a seed to initialize dropout.
        ///    params_size: The size of the params buffer that should be allocated and
        ///    initialized for this RNN model. Note that this params buffer may not be
        ///    compatible across GPUs. Please use CudnnRNNParamsWeights and
        ///    CudnnRNNParamsBiases to save and restore them in a way that is compatible
        ///    across different runs.
        /// </remarks>
        public static Tensor cudnn_r_n_n_params_size (Tensor num_layers, Tensor num_units, Tensor input_size, TF_DataType T, TF_DataType S, string rnn_mode = null, string input_mode = null, string direction = null, float? dropout = null, int? seed = null, int? seed2 = null, string name = "CudnnRNNParamsSize")
        {
            var dict = new Dictionary<string, object>();
            dict["num_layers"] = num_layers;
            dict["num_units"] = num_units;
            dict["input_size"] = input_size;
            dict["T"] = T;
            dict["S"] = S;
            if (rnn_mode != null)
                dict["rnn_mode"] = rnn_mode;
            if (input_mode != null)
                dict["input_mode"] = input_mode;
            if (direction != null)
                dict["direction"] = direction;
            if (dropout.HasValue)
                dict["dropout"] = dropout.Value;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("CudnnRNNParamsSize", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Retrieves CudnnRNN params in canonical form.
        /// </summary>
        /// <param name="num_layers">
        /// </param>
        /// <param name="num_units">
        /// </param>
        /// <param name="input_size">
        /// </param>
        /// <param name="parameters">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CudnnRNNParamsToCanonical'.
        /// </param>
        /// <param name="num_params">
        ///    Optional argument
        /// </param>
        /// <param name="rnn_mode">
        /// </param>
        /// <param name="input_mode">
        /// </param>
        /// <param name="direction">
        /// </param>
        /// <param name="dropout">
        /// </param>
        /// <param name="seed">
        /// </param>
        /// <param name="seed2">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    weights :
        ///    biases :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Retrieves a set of weights from the opaque params buffer that can be saved and
        ///    restored in a way compatible with future runs.
        ///    
        ///    Note that the params buffer may not be compatible across different GPUs. So any
        ///    save and restoration should be converted to and from the canonical weights and
        ///    biases.
        ///    
        ///    num_layers: Specifies the number of layers in the RNN model.
        ///    num_units: Specifies the size of the hidden state.
        ///    input_size: Specifies the size of the input state.
        ///    num_params: number of parameter sets for all layers.
        ///    Each layer may contain multiple parameter sets, with each set consisting of
        ///    a weight matrix and a bias vector.
        ///    weights: the canonical form of weights that can be used for saving
        ///    and restoration. They are more likely to be compatible across different
        ///    generations.
        ///    biases: the canonical form of biases that can be used for saving
        ///    and restoration. They are more likely to be compatible across different
        ///    generations.
        ///    rnn_mode: Indicates the type of the RNN model.
        ///    input_mode: Indicate whether there is a linear projection between the input and
        ///    The actual computation before the first layer. 'skip_input' is only allowed
        ///    when input_size == num_units; 'auto_select' implies 'skip_input' when
        ///    input_size == num_units; otherwise, it implies 'linear_input'.
        ///    direction: Indicates whether a bidirectional model will be used.
        ///    dir = (direction == bidirectional) ? 2 : 1
        ///    dropout: dropout probability. When set to 0., dropout is disabled.
        ///    seed: the 1st part of a seed to initialize dropout.
        ///    seed2: the 2nd part of a seed to initialize dropout.
        /// </remarks>
        public static (Tensor[] weights, Tensor[] biases) cudnn_r_n_n_params_to_canonical (Tensor num_layers, Tensor num_units, Tensor input_size, Tensor parameters, int num_params, string rnn_mode = null, string input_mode = null, string direction = null, float? dropout = null, int? seed = null, int? seed2 = null, string name = "CudnnRNNParamsToCanonical")
        {
            var dict = new Dictionary<string, object>();
            dict["num_layers"] = num_layers;
            dict["num_units"] = num_units;
            dict["input_size"] = input_size;
            dict["params"] = parameters;
            dict["num_params"] = num_params;
            if (rnn_mode != null)
                dict["rnn_mode"] = rnn_mode;
            if (input_mode != null)
                dict["input_mode"] = input_mode;
            if (direction != null)
                dict["direction"] = direction;
            if (dropout.HasValue)
                dict["dropout"] = dropout.Value;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("CudnnRNNParamsToCanonical", name: name, keywords: dict);
            int _idx = 0;
            var weights = Enumerable.Range(0, op.OutputListLength("weights")).Select(_ => op.outputs[_idx++]).ToArray();
            var biases = Enumerable.Range(0, op.OutputListLength("biases")).Select(_ => op.outputs[_idx++]).ToArray();
            return (weights, biases);
        }

        /// <summary>
        ///    A RNN backed by cuDNN.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="input_h">
        /// </param>
        /// <param name="input_c">
        /// </param>
        /// <param name="parameters">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'CudnnRNNV2'.
        /// </param>
        /// <param name="rnn_mode">
        /// </param>
        /// <param name="input_mode">
        /// </param>
        /// <param name="direction">
        /// </param>
        /// <param name="dropout">
        /// </param>
        /// <param name="seed">
        /// </param>
        /// <param name="seed2">
        /// </param>
        /// <param name="is_training">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output :
        ///    output_h :
        ///    output_c :
        ///    reserve_space :
        ///    host_reserved :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Computes the RNN from the input and initial states, with respect to the params
        ///    buffer. Produces one extra output "host_reserved" than CudnnRNN.
        ///    
        ///    rnn_mode: Indicates the type of the RNN model.
        ///    input_mode: Indicates whether there is a linear projection between the input and
        ///    the actual computation before the first layer. 'skip_input' is only allowed
        ///    when input_size == num_units; 'auto_select' implies 'skip_input' when
        ///    input_size == num_units; otherwise, it implies 'linear_input'.
        ///    direction: Indicates whether a bidirectional model will be used. Should be
        ///    "unidirectional" or "bidirectional".
        ///    dropout: Dropout probability. When set to 0., dropout is disabled.
        ///    seed: The 1st part of a seed to initialize dropout.
        ///    seed2: The 2nd part of a seed to initialize dropout.
        ///    input: A 3-D tensor with the shape of [seq_length, batch_size, input_size].
        ///    input_h: A 3-D tensor with the shape of [num_layer * dir, batch_size,
        ///    num_units].
        ///    input_c: For LSTM, a 3-D tensor with the shape of
        ///    [num_layer * dir, batch, num_units]. For other models, it is ignored.
        ///    params: A 1-D tensor that contains the weights and biases in an opaque layout.
        ///    The size must be created through CudnnRNNParamsSize, and initialized
        ///    separately. Note that they might not be compatible across different
        ///    generations. So it is a good idea to save and restore
        ///    output: A 3-D tensor with the shape of [seq_length, batch_size,
        ///    dir * num_units].
        ///    output_h: The same shape has input_h.
        ///    output_c: The same shape as input_c for LSTM. An empty tensor for other models.
        ///    is_training: Indicates whether this operation is used for inferenece or
        ///    training.
        ///    reserve_space: An opaque tensor that can be used in backprop calculation. It
        ///    is only produced if is_training is true.
        ///    host_reserved: An opaque tensor that can be used in backprop calculation. It is
        ///    only produced if is_training is true. It is output on host memory rather than
        ///    device memory.
        /// </remarks>
        public static (Tensor output, Tensor output_h, Tensor output_c, Tensor reserve_space, Tensor host_reserved) cudnn_r_n_n_v2 (Tensor input, Tensor input_h, Tensor input_c, Tensor parameters, string rnn_mode = null, string input_mode = null, string direction = null, float? dropout = null, int? seed = null, int? seed2 = null, bool? is_training = null, string name = "CudnnRNNV2")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["input_h"] = input_h;
            dict["input_c"] = input_c;
            dict["params"] = parameters;
            if (rnn_mode != null)
                dict["rnn_mode"] = rnn_mode;
            if (input_mode != null)
                dict["input_mode"] = input_mode;
            if (direction != null)
                dict["direction"] = direction;
            if (dropout.HasValue)
                dict["dropout"] = dropout.Value;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            if (is_training.HasValue)
                dict["is_training"] = is_training.Value;
            var op = _op_def_lib._apply_op_helper("CudnnRNNV2", name: name, keywords: dict);
            int _idx = 0;
            var output = op.outputs[_idx++];
            var output_h = op.outputs[_idx++];
            var output_c = op.outputs[_idx++];
            var reserve_space = op.outputs[_idx++];
            var host_reserved = op.outputs[_idx++];
            return (output, output_h, output_c, reserve_space, host_reserved);
        }

        /// <summary>
        ///    Compute the cumulative product of the tensor <c>x</c> along <c>axis</c>.
        /// </summary>
        /// <param name="x">
        ///    A <c>Tensor</c>. Must be one of the following types: <c>float32</c>, <c>float64</c>,
        ///    <c>int64</c>, <c>int32</c>, <c>uint8</c>, <c>uint16</c>, <c>int16</c>, <c>int8</c>, <c>complex64</c>,
        ///    <c>complex128</c>, <c>qint8</c>, <c>quint8</c>, <c>qint32</c>, <c>half</c>.
        /// </param>
        /// <param name="axis">
        ///    A <c>Tensor</c> of type <c>int32</c> (default: 0). Must be in the range
        ///    <c>[-rank(x), rank(x))</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Cumprod'.
        /// </param>
        /// <param name="exclusive">
        ///    If <c>True</c>, perform exclusive cumprod.
        /// </param>
        /// <param name="reverse">
        ///    A <c>bool</c> (default: False).
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    By default, this op performs an inclusive cumprod, which means that the first
        ///    element of the input is identical to the first element of the output:
        ///    
        ///   <code>
        ///    tf.cumprod([a, b, c])  # =&amp;gt; [a, a * b, a * b * c]
        ///   </code>
        ///    
        ///    By setting the <c>exclusive</c> kwarg to <c>True</c>, an exclusive cumprod is
        ///    performed instead:
        ///    
        ///   <code>
        ///    tf.cumprod([a, b, c], exclusive=True)  # =&amp;gt; [1, a, a * b]
        ///   </code>
        ///    
        ///    By setting the <c>reverse</c> kwarg to <c>True</c>, the cumprod is performed in the
        ///    opposite direction:
        ///    
        ///   <code>
        ///    tf.cumprod([a, b, c], reverse=True)  # =&amp;gt; [a * b * c, b * c, c]
        ///   </code>
        ///    
        ///    This is more efficient than using separate <c>tf.reverse</c> ops.
        ///    
        ///    The <c>reverse</c> and <c>exclusive</c> kwargs can also be combined:
        ///    
        ///   <code>
        ///    tf.cumprod([a, b, c], exclusive=True, reverse=True)  # =&amp;gt; [b * c, c, 1]
        ///   </code>
        /// </remarks>
        public static Tensor cumprod (Tensor x, Tensor axis, bool? exclusive = null, bool? reverse = null, string name = "Cumprod")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["axis"] = axis;
            if (exclusive.HasValue)
                dict["exclusive"] = exclusive.Value;
            if (reverse.HasValue)
                dict["reverse"] = reverse.Value;
            var op = _op_def_lib._apply_op_helper("Cumprod", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Compute the cumulative sum of the tensor <c>x</c> along <c>axis</c>.
        /// </summary>
        /// <param name="x">
        ///    A <c>Tensor</c>. Must be one of the following types: <c>float32</c>, <c>float64</c>,
        ///    <c>int64</c>, <c>int32</c>, <c>uint8</c>, <c>uint16</c>, <c>int16</c>, <c>int8</c>, <c>complex64</c>,
        ///    <c>complex128</c>, <c>qint8</c>, <c>quint8</c>, <c>qint32</c>, <c>half</c>.
        /// </param>
        /// <param name="axis">
        ///    A <c>Tensor</c> of type <c>int32</c> (default: 0). Must be in the range
        ///    <c>[-rank(x), rank(x))</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Cumsum'.
        /// </param>
        /// <param name="exclusive">
        ///    If <c>True</c>, perform exclusive cumsum.
        /// </param>
        /// <param name="reverse">
        ///    A <c>bool</c> (default: False).
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    By default, this op performs an inclusive cumsum, which means that the first
        ///    element of the input is identical to the first element of the output:
        ///    
        ///   <code>
        ///    tf.cumsum([a, b, c])  # =&amp;gt; [a, a + b, a + b + c]
        ///   </code>
        ///    
        ///    By setting the <c>exclusive</c> kwarg to <c>True</c>, an exclusive cumsum is
        ///    performed instead:
        ///    
        ///   <code>
        ///    tf.cumsum([a, b, c], exclusive=True)  # =&amp;gt; [0, a, a + b]
        ///   </code>
        ///    
        ///    By setting the <c>reverse</c> kwarg to <c>True</c>, the cumsum is performed in the
        ///    opposite direction:
        ///    
        ///   <code>
        ///    tf.cumsum([a, b, c], reverse=True)  # =&amp;gt; [a + b + c, b + c, c]
        ///   </code>
        ///    
        ///    This is more efficient than using separate <c>tf.reverse</c> ops.
        ///    
        ///    The <c>reverse</c> and <c>exclusive</c> kwargs can also be combined:
        ///    
        ///   <code>
        ///    tf.cumsum([a, b, c], exclusive=True, reverse=True)  # =&amp;gt; [b + c, c, 0]
        ///   </code>
        /// </remarks>
        public static Tensor cumsum (Tensor x, Tensor axis, bool? exclusive = null, bool? reverse = null, string name = "Cumsum")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["axis"] = axis;
            if (exclusive.HasValue)
                dict["exclusive"] = exclusive.Value;
            if (reverse.HasValue)
                dict["reverse"] = reverse.Value;
            var op = _op_def_lib._apply_op_helper("Cumsum", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the dimension index in the destination data format given the one in
        /// </summary>
        /// <param name="x">
        ///    A Tensor with each element as a dimension index in source data format.
        ///    Must be in the range [-4, 4).
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DataFormatDimMap'.
        /// </param>
        /// <param name="src_format">
        ///    source data format.
        /// </param>
        /// <param name="dst_format">
        ///    destination data format.
        /// </param>
        /// <returns>
        ///    A Tensor with each element as a dimension index in destination data format.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    the source data format.
        /// </remarks>
        public static Tensor data_format_dim_map (Tensor x, string src_format = null, string dst_format = null, string name = "DataFormatDimMap")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            if (src_format != null)
                dict["src_format"] = src_format;
            if (dst_format != null)
                dict["dst_format"] = dst_format;
            var op = _op_def_lib._apply_op_helper("DataFormatDimMap", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the permuted vector/tensor in the destination data format given the
        /// </summary>
        /// <param name="x">
        ///    Vector of size 4 or Tensor of shape (4, 2) in source data format.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DataFormatVecPermute'.
        /// </param>
        /// <param name="src_format">
        ///    source data format.
        /// </param>
        /// <param name="dst_format">
        ///    destination data format.
        /// </param>
        /// <returns>
        ///    Vector of size 4 or Tensor of shape (4, 2) in destination data format.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    one in the source data format.
        /// </remarks>
        public static Tensor data_format_vec_permute (Tensor x, string src_format = null, string dst_format = null, string name = "DataFormatVecPermute")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            if (src_format != null)
                dict["src_format"] = src_format;
            if (dst_format != null)
                dict["dst_format"] = dst_format;
            var op = _op_def_lib._apply_op_helper("DataFormatVecPermute", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns a serialized GraphDef representing <c>input_dataset</c>.
        /// </summary>
        /// <param name="input_dataset">
        ///    A variant tensor representing the dataset to return the graph representation for.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DatasetToGraph'.
        /// </param>
        /// <returns>
        ///    The graph representation of the dataset (as serialized GraphDef).
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Returns a graph representation for <c>input_dataset</c>.
        /// </remarks>
        public static Tensor dataset_to_graph (Tensor input_dataset, string name = "DatasetToGraph")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            var op = _op_def_lib._apply_op_helper("DatasetToGraph", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Outputs the single element from the given dataset.
        /// </summary>
        /// <param name="dataset">
        ///    A handle to a dataset that contains a single element.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DatasetToSingleElement'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The components of the single element of <c>input</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor[] dataset_to_single_element (Tensor dataset, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "DatasetToSingleElement")
        {
            var dict = new Dictionary<string, object>();
            dict["dataset"] = dataset;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("DatasetToSingleElement", name: name, keywords: dict);
            int _idx = 0;
            var components = Enumerable.Range(0, op.OutputListLength("components")).Select(_ => op.outputs[_idx++]).ToArray();
            return (components);
        }

        /// <summary>
        ///    Writes the given dataset to the given file using the TFRecord format.
        /// </summary>
        /// <param name="input_dataset">
        ///    A variant tensor representing the dataset to write.
        /// </param>
        /// <param name="filename">
        ///    A scalar string tensor representing the filename to use.
        /// </param>
        /// <param name="compression_type">
        ///    A scalar string tensor containing either (i) the empty string (no
        ///    compression), (ii) "ZLIB", or (iii) "GZIP".
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DatasetToTFRecord'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation dataset_to_t_f_record (Tensor input_dataset, Tensor filename, Tensor compression_type, string name = "DatasetToTFRecord")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["filename"] = filename;
            dict["compression_type"] = compression_type;
            var op = _op_def_lib._apply_op_helper("DatasetToTFRecord", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Identity op for gradient debugging.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DebugGradientIdentity'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op is hidden from public in Python. It is used by TensorFlow Debugger to
        ///    register gradient tensors for gradient debugging.
        ///    This op operates on non-reference-type tensors.
        /// </remarks>
        public static Tensor debug_gradient_identity (Tensor input, string name = "DebugGradientIdentity")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("DebugGradientIdentity", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Identity op for gradient debugging.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DebugGradientRefIdentity'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op is hidden from public in Python. It is used by TensorFlow Debugger to
        ///    register gradient tensors for gradient debugging.
        ///    This op operates on reference-type tensors.
        /// </remarks>
        public static Tensor debug_gradient_ref_identity (Tensor input, string name = "DebugGradientRefIdentity")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("DebugGradientRefIdentity", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Debug Identity Op.
        /// </summary>
        /// <param name="input">
        ///    Input tensor, non-Reference type.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DebugIdentity'.
        /// </param>
        /// <param name="device_name">
        /// </param>
        /// <param name="tensor_name">
        ///    Name of the input tensor.
        /// </param>
        /// <param name="debug_urls">
        ///    List of URLs to debug targets, e.g.,
        ///    file:///foo/tfdbg_dump, grpc:://localhost:11011
        /// </param>
        /// <param name="gated_grpc">
        ///    Whether this op will be gated. If any of the debug_urls of this
        ///    debug node is of the grpc:// scheme, when the value of this attribute is set
        ///    to True, the data will not actually be sent via the grpc stream unless this
        ///    debug op has been enabled at the debug_url. If all of the debug_urls of this
        ///    debug node are of the grpc:// scheme and the debug op is enabled at none of
        ///    them, the output will be an empty Tensor.
        /// </param>
        /// <returns>
        ///    Output tensor that equals the input tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Provides an identity mapping of the non-Ref type input tensor for debugging.
        /// </remarks>
        public static Tensor debug_identity (Tensor input, string device_name = null, string tensor_name = null, string[] debug_urls = null, bool? gated_grpc = null, string name = "DebugIdentity")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (device_name != null)
                dict["device_name"] = device_name;
            if (tensor_name != null)
                dict["tensor_name"] = tensor_name;
            if (debug_urls != null)
                dict["debug_urls"] = debug_urls;
            if (gated_grpc.HasValue)
                dict["gated_grpc"] = gated_grpc.Value;
            var op = _op_def_lib._apply_op_helper("DebugIdentity", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Debug NaN Value Counter Op
        /// </summary>
        /// <param name="input">
        ///    Input tensor, non-Reference type.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DebugNanCount'.
        /// </param>
        /// <param name="device_name">
        /// </param>
        /// <param name="tensor_name">
        ///    Name of the input tensor.
        /// </param>
        /// <param name="debug_urls">
        ///    List of URLs to debug targets, e.g.,
        ///    file:///foo/tfdbg_dump, grpc:://localhost:11011.
        /// </param>
        /// <param name="gated_grpc">
        ///    Whether this op will be gated. If any of the debug_urls of this
        ///    debug node is of the grpc:// scheme, when the value of this attribute is set
        ///    to True, the data will not actually be sent via the grpc stream unless this
        ///    debug op has been enabled at the debug_url. If all of the debug_urls of this
        ///    debug node are of the grpc:// scheme and the debug op is enabled at none of
        ///    them, the output will be an empty Tensor.
        /// </param>
        /// <returns>
        ///    An integer output tensor that is the number of NaNs in the input.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Counts number of NaNs in the input tensor, for debugging.
        /// </remarks>
        public static Tensor debug_nan_count (Tensor input, string device_name = null, string tensor_name = null, string[] debug_urls = null, bool? gated_grpc = null, string name = "DebugNanCount")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (device_name != null)
                dict["device_name"] = device_name;
            if (tensor_name != null)
                dict["tensor_name"] = tensor_name;
            if (debug_urls != null)
                dict["debug_urls"] = debug_urls;
            if (gated_grpc.HasValue)
                dict["gated_grpc"] = gated_grpc.Value;
            var op = _op_def_lib._apply_op_helper("DebugNanCount", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Debug Numeric Summary Op.
        /// </summary>
        /// <param name="input">
        ///    Input tensor, non-Reference type, float or double.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DebugNumericSummary'.
        /// </param>
        /// <param name="device_name">
        /// </param>
        /// <param name="tensor_name">
        ///    Name of the input tensor.
        /// </param>
        /// <param name="debug_urls">
        ///    List of URLs to debug targets, e.g.,
        ///    file:///foo/tfdbg_dump, grpc:://localhost:11011
        /// </param>
        /// <param name="lower_bound">
        ///    (float) The lower bound &amp;lt;= which values will be included in the
        ///    generalized -inf count. Default: -inf.
        /// </param>
        /// <param name="upper_bound">
        ///    (float) The upper bound &amp;gt;= which values will be included in the
        ///    generalized +inf count. Default: +inf.
        /// </param>
        /// <param name="mute_if_healthy">
        ///    (bool) Do not send data to the debug URLs unless at least one
        ///    of elements [2], [3] and [7] (i.e., the nan count and the generalized -inf and
        ///    inf counts) is non-zero.
        /// </param>
        /// <param name="gated_grpc">
        ///    Whether this op will be gated. If any of the debug_urls of this
        ///    debug node is of the grpc:// scheme, when the value of this attribute is set
        ///    to True, the data will not actually be sent via the grpc stream unless this
        ///    debug op has been enabled at the debug_url. If all of the debug_urls of this
        ///    debug node are of the grpc:// scheme and the debug op is enabled at none of
        ///    them, the output will be an empty Tensor.
        /// </param>
        /// <returns>
        ///    A double tensor of shape [14 + nDimensions], where nDimensions is the
        ///    the number of dimensions of the tensor's shape. The elements of output are:
        ///    [0]: is initialized (1.0) or not (0.0).
        ///    [1]: total number of elements
        ///    [2]: NaN element count
        ///    [3]: generalized -inf count: elements &amp;lt;= lower_bound. lower_bound is -inf by
        ///    default.
        ///    [4]: negative element count (excluding -inf), if lower_bound is the default
        ///    -inf. Otherwise, this is the count of elements &amp;gt; lower_bound and &amp;lt; 0.
        ///    [5]: zero element count
        ///    [6]: positive element count (excluding +inf), if upper_bound is the default
        ///    -inf. Otherwise, this is the count of elements &amp;lt; upper_bound and &amp;gt; 0.
        ///    [7]: generalized +inf count, elements &amp;gt;= upper_bound. upper_bound is +inf by
        ///    default.
        ///    Output elements [1:8] are all zero, if the tensor is uninitialized.
        ///    [8]: minimum of all non-inf and non-NaN elements.
        ///    If uninitialized or no such element exists: +inf.
        ///    [9]: maximum of all non-inf and non-NaN elements.
        ///    If uninitialized or no such element exists: -inf.
        ///    [10]: mean of all non-inf and non-NaN elements.
        ///    If uninitialized or no such element exists: NaN.
        ///    [11]: variance of all non-inf and non-NaN elements.
        ///    If uninitialized or no such element exists: NaN.
        ///    [12]: Data type of the tensor encoded as an enum integer. See the DataType
        ///    proto for more details.
        ///    [13]: Number of dimensions of the tensor (ndims).
        ///    [14+]: Sizes of the dimensions.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Provide a basic summary of numeric value types, range and distribution.
        /// </remarks>
        public static Tensor debug_numeric_summary (Tensor input, string device_name = null, string tensor_name = null, string[] debug_urls = null, float? lower_bound = null, float? upper_bound = null, bool? mute_if_healthy = null, bool? gated_grpc = null, string name = "DebugNumericSummary")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (device_name != null)
                dict["device_name"] = device_name;
            if (tensor_name != null)
                dict["tensor_name"] = tensor_name;
            if (debug_urls != null)
                dict["debug_urls"] = debug_urls;
            if (lower_bound.HasValue)
                dict["lower_bound"] = lower_bound.Value;
            if (upper_bound.HasValue)
                dict["upper_bound"] = upper_bound.Value;
            if (mute_if_healthy.HasValue)
                dict["mute_if_healthy"] = mute_if_healthy.Value;
            if (gated_grpc.HasValue)
                dict["gated_grpc"] = gated_grpc.Value;
            var op = _op_def_lib._apply_op_helper("DebugNumericSummary", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Decode and Crop a JPEG-encoded image to a uint8 tensor.
        /// </summary>
        /// <param name="contents">
        ///    0-D.  The JPEG-encoded image.
        /// </param>
        /// <param name="crop_window">
        ///    1-D.  The crop window: [crop_y, crop_x, crop_height, crop_width].
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DecodeAndCropJpeg'.
        /// </param>
        /// <param name="channels">
        ///    Number of color channels for the decoded image.
        /// </param>
        /// <param name="ratio">
        ///    Downscaling ratio.
        /// </param>
        /// <param name="fancy_upscaling">
        ///    If true use a slower but nicer upscaling of the
        ///    chroma planes (yuv420/422 only).
        /// </param>
        /// <param name="try_recover_truncated">
        ///    If true try to recover an image from truncated input.
        /// </param>
        /// <param name="acceptable_fraction">
        ///    The minimum required fraction of lines before a truncated
        ///    input is accepted.
        /// </param>
        /// <param name="dct_method">
        ///    string specifying a hint about the algorithm used for
        ///    decompression.  Defaults to "" which maps to a system-specific
        ///    default.  Currently valid values are ["INTEGER_FAST",
        ///    "INTEGER_ACCURATE"].  The hint may be ignored (e.g., the internal
        ///    jpeg library changes to a version that does not have that specific
        ///    option.)
        /// </param>
        /// <returns>
        ///    3-D with shape <c>[height, width, channels]</c>..
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The attr <c>channels</c> indicates the desired number of color channels for the
        ///    decoded image.
        ///    
        ///    Accepted values are:
        ///    
        ///    *   0: Use the number of channels in the JPEG-encoded image.
        ///    *   1: output a grayscale image.
        ///    *   3: output an RGB image.
        ///    
        ///    If needed, the JPEG-encoded image is transformed to match the requested number
        ///    of color channels.
        ///    
        ///    The attr <c>ratio</c> allows downscaling the image by an integer factor during
        ///    decoding.  Allowed values are: 1, 2, 4, and 8.  This is much faster than
        ///    downscaling the image later.
        ///    
        ///    
        ///    It is equivalent to a combination of decode and crop, but much faster by only
        ///    decoding partial jpeg image.
        /// </remarks>
        public static Tensor decode_and_crop_jpeg (Tensor contents, Tensor crop_window, int? channels = null, int? ratio = null, bool? fancy_upscaling = null, bool? try_recover_truncated = null, float? acceptable_fraction = null, string dct_method = null, string name = "DecodeAndCropJpeg")
        {
            var dict = new Dictionary<string, object>();
            dict["contents"] = contents;
            dict["crop_window"] = crop_window;
            if (channels.HasValue)
                dict["channels"] = channels.Value;
            if (ratio.HasValue)
                dict["ratio"] = ratio.Value;
            if (fancy_upscaling.HasValue)
                dict["fancy_upscaling"] = fancy_upscaling.Value;
            if (try_recover_truncated.HasValue)
                dict["try_recover_truncated"] = try_recover_truncated.Value;
            if (acceptable_fraction.HasValue)
                dict["acceptable_fraction"] = acceptable_fraction.Value;
            if (dct_method != null)
                dict["dct_method"] = dct_method;
            var op = _op_def_lib._apply_op_helper("DecodeAndCropJpeg", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Decode web-safe base64-encoded strings.
        /// </summary>
        /// <param name="input">
        ///    Base64 strings to decode.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DecodeBase64'.
        /// </param>
        /// <returns>
        ///    Decoded strings.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Input may or may not have padding at the end. See EncodeBase64 for padding.
        ///    Web-safe means that input must use - and _ instead of + and /.
        /// </remarks>
        public static Tensor decode_base64 (Tensor input, string name = "DecodeBase64")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("DecodeBase64", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Decode the first frame of a BMP-encoded image to a uint8 tensor.
        /// </summary>
        /// <param name="contents">
        ///    0-D.  The BMP-encoded image.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DecodeBmp'.
        /// </param>
        /// <param name="channels">
        /// </param>
        /// <returns>
        ///    3-D with shape <c>[height, width, channels]</c>. RGB order
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The attr <c>channels</c> indicates the desired number of color channels for the
        ///    decoded image.
        ///    
        ///    Accepted values are:
        ///    
        ///    *   0: Use the number of channels in the BMP-encoded image.
        ///    *   3: output an RGB image.
        ///    *   4: output an RGBA image.
        /// </remarks>
        public static Tensor decode_bmp (Tensor contents, int? channels = null, string name = "DecodeBmp")
        {
            var dict = new Dictionary<string, object>();
            dict["contents"] = contents;
            if (channels.HasValue)
                dict["channels"] = channels.Value;
            var op = _op_def_lib._apply_op_helper("DecodeBmp", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Convert CSV records to tensors. Each column maps to one tensor.
        /// </summary>
        /// <param name="records">
        ///    Each string is a record/row in the csv and all records should have
        ///    the same format.
        /// </param>
        /// <param name="record_defaults">
        ///    One tensor per column of the input record, with either a
        ///    scalar default value for that column or an empty vector if the column is
        ///    required.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DecodeCSV'.
        /// </param>
        /// <param name="field_delim">
        ///    char delimiter to separate fields in a record.
        /// </param>
        /// <param name="use_quote_delim">
        ///    If false, treats double quotation marks as regular
        ///    characters inside of the string fields (ignoring RFC 4180, Section 2,
        ///    Bullet 5).
        /// </param>
        /// <param name="na_value">
        ///    Additional string to recognize as NA/NaN.
        /// </param>
        /// <param name="select_cols">
        /// </param>
        /// <returns>
        ///    Each tensor will have the same shape as records.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    RFC 4180 format is expected for the CSV records.
        ///    (https://tools.ietf.org/html/rfc4180)
        ///    Note that we allow leading and trailing spaces with int or float field.
        /// </remarks>
        public static Tensor[] decode_c_s_v (Tensor records, Tensor[] record_defaults, string field_delim = null, bool? use_quote_delim = null, string na_value = null, int[] select_cols = null, string name = "DecodeCSV")
        {
            var dict = new Dictionary<string, object>();
            dict["records"] = records;
            dict["record_defaults"] = record_defaults;
            if (field_delim != null)
                dict["field_delim"] = field_delim;
            if (use_quote_delim.HasValue)
                dict["use_quote_delim"] = use_quote_delim.Value;
            if (na_value != null)
                dict["na_value"] = na_value;
            if (select_cols != null)
                dict["select_cols"] = select_cols;
            var op = _op_def_lib._apply_op_helper("DecodeCSV", name: name, keywords: dict);
            int _idx = 0;
            var output = Enumerable.Range(0, op.OutputListLength("output")).Select(_ => op.outputs[_idx++]).ToArray();
            return (output);
        }

        /// <summary>
        ///    Decompress strings.
        /// </summary>
        /// <param name="bytes">
        ///    A Tensor of string which is compressed.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DecodeCompressed'.
        /// </param>
        /// <param name="compression_type">
        ///    A scalar containing either (i) the empty string (no
        ///    compression), (ii) "ZLIB", or (iii) "GZIP".
        /// </param>
        /// <returns>
        ///    A Tensor with the same shape as input <c>bytes</c>, uncompressed
        ///    from bytes.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op decompresses each element of the <c>bytes</c> input <c>Tensor</c>, which
        ///    is assumed to be compressed using the given <c>compression_type</c>.
        ///    
        ///    The <c>output</c> is a string <c>Tensor</c> of the same shape as <c>bytes</c>,
        ///    each element containing the decompressed data from the corresponding
        ///    element in <c>bytes</c>.
        /// </remarks>
        public static Tensor decode_compressed (Tensor bytes, string compression_type = null, string name = "DecodeCompressed")
        {
            var dict = new Dictionary<string, object>();
            dict["bytes"] = bytes;
            if (compression_type != null)
                dict["compression_type"] = compression_type;
            var op = _op_def_lib._apply_op_helper("DecodeCompressed", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Decode the first frame of a GIF-encoded image to a uint8 tensor.
        /// </summary>
        /// <param name="contents">
        ///    0-D.  The GIF-encoded image.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DecodeGif'.
        /// </param>
        /// <returns>
        ///    4-D with shape <c>[num_frames, height, width, 3]</c>. RGB order
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    GIF with frame or transparency compression are not supported
        ///    convert animated GIF from compressed to uncompressed by:
        ///    
        ///    convert $src.gif -coalesce $dst.gif
        ///    
        ///    This op also supports decoding JPEGs and PNGs, though it is cleaner to use
        ///    <c>tf.image.decode_image</c>.
        /// </remarks>
        public static Tensor decode_gif (Tensor contents, string name = "DecodeGif")
        {
            var dict = new Dictionary<string, object>();
            dict["contents"] = contents;
            var op = _op_def_lib._apply_op_helper("DecodeGif", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Convert JSON-encoded Example records to binary protocol buffer strings.
        /// </summary>
        /// <param name="json_examples">
        ///    Each string is a JSON object serialized according to the JSON
        ///    mapping of the Example proto.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DecodeJSONExample'.
        /// </param>
        /// <returns>
        ///    Each string is a binary Example protocol buffer corresponding
        ///    to the respective element of <c>json_examples</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op translates a tensor containing Example records, encoded using
        ///    the [standard JSON
        ///    mapping](https://developers.google.com/protocol-buffers/docs/proto3#json),
        ///    into a tensor containing the same records encoded as binary protocol
        ///    buffers. The resulting tensor can then be fed to any of the other
        ///    Example-parsing ops.
        /// </remarks>
        public static Tensor decode_j_s_o_n_example (Tensor json_examples, string name = "DecodeJSONExample")
        {
            var dict = new Dictionary<string, object>();
            dict["json_examples"] = json_examples;
            var op = _op_def_lib._apply_op_helper("DecodeJSONExample", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Decode a JPEG-encoded image to a uint8 tensor.
        /// </summary>
        /// <param name="contents">
        ///    0-D.  The JPEG-encoded image.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DecodeJpeg'.
        /// </param>
        /// <param name="channels">
        ///    Number of color channels for the decoded image.
        /// </param>
        /// <param name="ratio">
        ///    Downscaling ratio.
        /// </param>
        /// <param name="fancy_upscaling">
        ///    If true use a slower but nicer upscaling of the
        ///    chroma planes (yuv420/422 only).
        /// </param>
        /// <param name="try_recover_truncated">
        ///    If true try to recover an image from truncated input.
        /// </param>
        /// <param name="acceptable_fraction">
        ///    The minimum required fraction of lines before a truncated
        ///    input is accepted.
        /// </param>
        /// <param name="dct_method">
        ///    string specifying a hint about the algorithm used for
        ///    decompression.  Defaults to "" which maps to a system-specific
        ///    default.  Currently valid values are ["INTEGER_FAST",
        ///    "INTEGER_ACCURATE"].  The hint may be ignored (e.g., the internal
        ///    jpeg library changes to a version that does not have that specific
        ///    option.)
        /// </param>
        /// <returns>
        ///    3-D with shape <c>[height, width, channels]</c>..
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The attr <c>channels</c> indicates the desired number of color channels for the
        ///    decoded image.
        ///    
        ///    Accepted values are:
        ///    
        ///    *   0: Use the number of channels in the JPEG-encoded image.
        ///    *   1: output a grayscale image.
        ///    *   3: output an RGB image.
        ///    
        ///    If needed, the JPEG-encoded image is transformed to match the requested number
        ///    of color channels.
        ///    
        ///    The attr <c>ratio</c> allows downscaling the image by an integer factor during
        ///    decoding.  Allowed values are: 1, 2, 4, and 8.  This is much faster than
        ///    downscaling the image later.
        ///    
        ///    
        ///    This op also supports decoding PNGs and non-animated GIFs since the interface is
        ///    the same, though it is cleaner to use <c>tf.image.decode_image</c>.
        /// </remarks>
        public static Tensor decode_jpeg (Tensor contents, int? channels = null, int? ratio = null, bool? fancy_upscaling = null, bool? try_recover_truncated = null, float? acceptable_fraction = null, string dct_method = null, string name = "DecodeJpeg")
        {
            var dict = new Dictionary<string, object>();
            dict["contents"] = contents;
            if (channels.HasValue)
                dict["channels"] = channels.Value;
            if (ratio.HasValue)
                dict["ratio"] = ratio.Value;
            if (fancy_upscaling.HasValue)
                dict["fancy_upscaling"] = fancy_upscaling.Value;
            if (try_recover_truncated.HasValue)
                dict["try_recover_truncated"] = try_recover_truncated.Value;
            if (acceptable_fraction.HasValue)
                dict["acceptable_fraction"] = acceptable_fraction.Value;
            if (dct_method != null)
                dict["dct_method"] = dct_method;
            var op = _op_def_lib._apply_op_helper("DecodeJpeg", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Decode a PNG-encoded image to a uint8 or uint16 tensor.
        /// </summary>
        /// <param name="contents">
        ///    0-D.  The PNG-encoded image.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DecodePng'.
        /// </param>
        /// <param name="channels">
        ///    Number of color channels for the decoded image.
        /// </param>
        /// <param name="dtype">
        /// </param>
        /// <returns>
        ///    3-D with shape <c>[height, width, channels]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The attr <c>channels</c> indicates the desired number of color channels for the
        ///    decoded image.
        ///    
        ///    Accepted values are:
        ///    
        ///    *   0: Use the number of channels in the PNG-encoded image.
        ///    *   1: output a grayscale image.
        ///    *   3: output an RGB image.
        ///    *   4: output an RGBA image.
        ///    
        ///    If needed, the PNG-encoded image is transformed to match the requested number
        ///    of color channels.
        ///    
        ///    This op also supports decoding JPEGs and non-animated GIFs since the interface
        ///    is the same, though it is cleaner to use <c>tf.image.decode_image</c>.
        /// </remarks>
        public static Tensor decode_png (Tensor contents, int? channels = null, TF_DataType? dtype = null, string name = "DecodePng")
        {
            var dict = new Dictionary<string, object>();
            dict["contents"] = contents;
            if (channels.HasValue)
                dict["channels"] = channels.Value;
            if (dtype.HasValue)
                dict["dtype"] = dtype.Value;
            var op = _op_def_lib._apply_op_helper("DecodePng", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    The op extracts fields from a serialized protocol buffers message into tensors.
        /// </summary>
        /// <param name="bytes">
        ///    Tensor of serialized protos with shape <c>batch_shape</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DecodeProtoV2'.
        /// </param>
        /// <param name="message_type">
        ///    Optional argument
        ///    Name of the proto message type to decode.
        /// </param>
        /// <param name="field_names">
        ///    Optional argument
        ///    List of strings containing proto field names.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        ///    List of TF types to use for the respective field in field_names.
        /// </param>
        /// <param name="descriptor_source">
        ///    Either the special value <c>local://</c> or a path to a file containing
        ///    a serialized <c>FileDescriptorSet</c>.
        /// </param>
        /// <param name="message_format">
        ///    Either <c>binary</c> or <c>text</c>.
        /// </param>
        /// <param name="sanitize">
        ///    Whether to sanitize the result or not.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    sizes : Tensor of int32 with shape <c>[batch_shape, len(field_names)]</c>.
        ///    Each entry is the number of values found for the corresponding field.
        ///    Optional fields may have 0 or 1 values.
        ///    values : List of tensors containing values for the corresponding field.
        ///    <c>values[i]</c> has datatype <c>output_types[i]</c>
        ///    and shape <c>[batch_shape, max(sizes[...,i])]</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    The <c>decode_proto</c> op extracts fields from a serialized protocol buffers
        ///    message into tensors.  The fields in <c>field_names</c> are decoded and converted
        ///    to the corresponding <c>output_types</c> if possible.
        ///    
        ///    A <c>message_type</c> name must be provided to give context for the field
        ///    names. The actual message descriptor can be looked up either in the
        ///    linked-in descriptor pool or a filename provided by the caller using
        ///    the <c>descriptor_source</c> attribute.
        ///    
        ///    Each output tensor is a dense tensor. This means that it is padded to
        ///    hold the largest number of repeated elements seen in the input
        ///    minibatch. (The shape is also padded by one to prevent zero-sized
        ///    dimensions). The actual repeat counts for each example in the
        ///    minibatch can be found in the <c>sizes</c> output. In many cases the output
        ///    of <c>decode_proto</c> is fed immediately into tf.squeeze if missing values
        ///    are not a concern. When using tf.squeeze, always pass the squeeze
        ///    dimension explicitly to avoid surprises.
        ///    
        ///    For the most part, the mapping between Proto field types and
        ///    TensorFlow dtypes is straightforward. However, there are a few
        ///    special cases:
        ///    
        ///    - A proto field that contains a submessage or group can only be converted
        ///    to <c>DT_STRING</c> (the serialized submessage). This is to reduce the
        ///    complexity of the API. The resulting string can be used as input
        ///    to another instance of the decode_proto op.
        ///    
        ///    - TensorFlow lacks support for unsigned integers. The ops represent uint64
        ///    types as a <c>DT_INT64</c> with the same twos-complement bit pattern
        ///    (the obvious way). Unsigned int32 values can be represented exactly by
        ///    specifying type <c>DT_INT64</c>, or using twos-complement if the caller
        ///    specifies <c>DT_INT32</c> in the <c>output_types</c> attribute.
        ///    
        ///    The <c>descriptor_source</c> attribute selects a source of protocol
        ///    descriptors to consult when looking up <c>message_type</c>. This may be a
        ///    filename containing a serialized <c>FileDescriptorSet</c> message,
        ///    or the special value <c>local://</c>, in which case only descriptors linked
        ///    into the code will be searched; the filename can be on any filesystem
        ///    accessible to TensorFlow.
        ///    
        ///    You can build a <c>descriptor_source</c> file using the <c>--descriptor_set_out</c>
        ///    and <c>--include_imports</c> options to the protocol compiler <c>protoc</c>.
        ///    
        ///    The <c>local://</c> database only covers descriptors linked into the
        ///    code via C++ libraries, not Python imports. You can link in a proto descriptor
        ///    by creating a cc_library target with alwayslink=1.
        ///    
        ///    Both binary and text proto serializations are supported, and can be
        ///    chosen using the <c>format</c> attribute.
        /// </remarks>
        public static (Tensor sizes, Tensor[] values) decode_proto_v2 (Tensor bytes, string message_type, string[] field_names, TF_DataType[] output_types, string descriptor_source = null, string message_format = null, bool? sanitize = null, string name = "DecodeProtoV2")
        {
            var dict = new Dictionary<string, object>();
            dict["bytes"] = bytes;
            dict["message_type"] = message_type;
            dict["field_names"] = field_names;
            dict["output_types"] = output_types;
            if (descriptor_source != null)
                dict["descriptor_source"] = descriptor_source;
            if (message_format != null)
                dict["message_format"] = message_format;
            if (sanitize.HasValue)
                dict["sanitize"] = sanitize.Value;
            var op = _op_def_lib._apply_op_helper("DecodeProtoV2", name: name, keywords: dict);
            int _idx = 0;
            var sizes = op.outputs[_idx++];
            var values = Enumerable.Range(0, op.OutputListLength("values")).Select(_ => op.outputs[_idx++]).ToArray();
            return (sizes, values);
        }

        /// <summary>
        ///    Reinterpret the bytes of a string as a vector of numbers.
        /// </summary>
        /// <param name="bytes">
        ///    All the elements must have the same length.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DecodeRaw'.
        /// </param>
        /// <param name="out_type">
        ///    Optional argument
        /// </param>
        /// <param name="little_endian">
        ///    Whether the input <c>bytes</c> are in little-endian order.
        ///    Ignored for <c>out_type</c> values that are stored in a single byte like
        ///    <c>uint8</c>.
        /// </param>
        /// <returns>
        ///    A Tensor with one more dimension than the input <c>bytes</c>.  The
        ///    added dimension will have size equal to the length of the elements
        ///    of <c>bytes</c> divided by the number of bytes to represent <c>out_type</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor decode_raw (Tensor bytes, TF_DataType out_type, bool? little_endian = null, string name = "DecodeRaw")
        {
            var dict = new Dictionary<string, object>();
            dict["bytes"] = bytes;
            dict["out_type"] = out_type;
            if (little_endian.HasValue)
                dict["little_endian"] = little_endian.Value;
            var op = _op_def_lib._apply_op_helper("DecodeRaw", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Decode a 16-bit PCM WAV file to a float tensor.
        /// </summary>
        /// <param name="contents">
        ///    The WAV-encoded audio, usually from a file.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DecodeWav'.
        /// </param>
        /// <param name="desired_channels">
        ///    Number of sample channels wanted.
        /// </param>
        /// <param name="desired_samples">
        ///    Length of audio requested.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    audio : 2-D with shape <c>[length, channels]</c>.
        ///    sample_rate : Scalar holding the sample rate found in the WAV header.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    The -32768 to 32767 signed 16-bit values will be scaled to -1.0 to 1.0 in float.
        ///    
        ///    When desired_channels is set, if the input contains fewer channels than this
        ///    then the last channel will be duplicated to give the requested number, else if
        ///    the input has more channels than requested then the additional channels will be
        ///    ignored.
        ///    
        ///    If desired_samples is set, then the audio will be cropped or padded with zeroes
        ///    to the requested length.
        ///    
        ///    The first output contains a Tensor with the content of the audio samples. The
        ///    lowest dimension will be the number of channels, and the second will be the
        ///    number of samples. For example, a ten-sample-long stereo WAV file should give an
        ///    output shape of [10, 2].
        /// </remarks>
        public static (Tensor audio, Tensor sample_rate) decode_wav (Tensor contents, int? desired_channels = null, int? desired_samples = null, string name = "DecodeWav")
        {
            var dict = new Dictionary<string, object>();
            dict["contents"] = contents;
            if (desired_channels.HasValue)
                dict["desired_channels"] = desired_channels.Value;
            if (desired_samples.HasValue)
                dict["desired_samples"] = desired_samples.Value;
            var op = _op_def_lib._apply_op_helper("DecodeWav", name: name, keywords: dict);
            int _idx = 0;
            var audio = op.outputs[_idx++];
            var sample_rate = op.outputs[_idx++];
            return (audio, sample_rate);
        }

        /// <summary>
        ///    Makes a copy of <c>x</c>.
        /// </summary>
        /// <param name="x">
        ///    The source tensor of type <c>T</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DeepCopy'.
        /// </param>
        /// <returns>
        ///    y: A <c>Tensor</c> of type <c>T</c>. A copy of <c>x</c>. Guaranteed that <c>y</c>
        ///    is not an alias of <c>x</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor deep_copy (Tensor x, string name = "DeepCopy")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("DeepCopy", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Delete the tensor specified by its handle in the session.
        /// </summary>
        /// <param name="handle">
        ///    The handle for a tensor stored in the session state.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DeleteSessionTensor'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation delete_session_tensor (Tensor handle, string name = "DeleteSessionTensor")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            var op = _op_def_lib._apply_op_helper("DeleteSessionTensor", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Applies set operation along last dimension of 2 <c>Tensor</c> inputs.
        /// </summary>
        /// <param name="set1">
        ///    <c>Tensor</c> with rank <c>n</c>. 1st <c>n-1</c> dimensions must be the same as <c>set2</c>.
        ///    Dimension <c>n</c> contains values in a set, duplicates are allowed but ignored.
        /// </param>
        /// <param name="set2">
        ///    <c>Tensor</c> with rank <c>n</c>. 1st <c>n-1</c> dimensions must be the same as <c>set1</c>.
        ///    Dimension <c>n</c> contains values in a set, duplicates are allowed but ignored.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DenseToDenseSetOperation'.
        /// </param>
        /// <param name="set_operation">
        ///    Optional argument
        /// </param>
        /// <param name="validate_indices">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    result_indices : 2D indices of a <c>SparseTensor</c>.
        ///    result_values : 1D values of a <c>SparseTensor</c>.
        ///    result_shape : 1D <c>Tensor</c> shape of a <c>SparseTensor</c>. <c>result_shape[0...n-1]</c> is
        ///    the same as the 1st <c>n-1</c> dimensions of <c>set1</c> and <c>set2</c>, <c>result_shape[n]</c>
        ///    is the max result set size across all <c>0...n-1</c> dimensions.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    See SetOperationOp::SetOperationFromContext for values of <c>set_operation</c>.
        ///    
        ///    Output <c>result</c> is a <c>SparseTensor</c> represented by <c>result_indices</c>,
        ///    <c>result_values</c>, and <c>result_shape</c>. For <c>set1</c> and <c>set2</c> ranked <c>n</c>, this
        ///    has rank <c>n</c> and the same 1st <c>n-1</c> dimensions as <c>set1</c> and <c>set2</c>. The <c>nth</c>
        ///    dimension contains the result of <c>set_operation</c> applied to the corresponding
        ///    <c>[0...n-1]</c> dimension of <c>set</c>.
        /// </remarks>
        public static (Tensor result_indices, Tensor result_values, Tensor result_shape) dense_to_dense_set_operation (Tensor set1, Tensor set2, string set_operation, bool? validate_indices = null, string name = "DenseToDenseSetOperation")
        {
            var dict = new Dictionary<string, object>();
            dict["set1"] = set1;
            dict["set2"] = set2;
            dict["set_operation"] = set_operation;
            if (validate_indices.HasValue)
                dict["validate_indices"] = validate_indices.Value;
            var op = _op_def_lib._apply_op_helper("DenseToDenseSetOperation", name: name, keywords: dict);
            int _idx = 0;
            var result_indices = op.outputs[_idx++];
            var result_values = op.outputs[_idx++];
            var result_shape = op.outputs[_idx++];
            return (result_indices, result_values, result_shape);
        }

        /// <summary>
        ///    Creates a dataset that batches input elements into a SparseTensor.
        /// </summary>
        /// <param name="input_dataset">
        ///    A handle to an input dataset. Must have a single component.
        /// </param>
        /// <param name="batch_size">
        ///    A scalar representing the number of elements to accumulate in a
        ///    batch.
        /// </param>
        /// <param name="row_shape">
        ///    A vector representing the dense shape of each row in the produced
        ///    SparseTensor. The shape may be partially specified, using <c>-1</c> to indicate
        ///    that a particular dimension should use the maximum size of all batch elements.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DenseToSparseBatchDataset'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor dense_to_sparse_batch_dataset (Tensor input_dataset, Tensor batch_size, Tensor row_shape, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "DenseToSparseBatchDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["batch_size"] = batch_size;
            dict["row_shape"] = row_shape;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("DenseToSparseBatchDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Applies set operation along last dimension of <c>Tensor</c> and <c>SparseTensor</c>.
        /// </summary>
        /// <param name="set1">
        ///    <c>Tensor</c> with rank <c>n</c>. 1st <c>n-1</c> dimensions must be the same as <c>set2</c>.
        ///    Dimension <c>n</c> contains values in a set, duplicates are allowed but ignored.
        /// </param>
        /// <param name="set2_indices">
        ///    2D <c>Tensor</c>, indices of a <c>SparseTensor</c>. Must be in row-major
        ///    order.
        /// </param>
        /// <param name="set2_values">
        ///    1D <c>Tensor</c>, values of a <c>SparseTensor</c>. Must be in row-major
        ///    order.
        /// </param>
        /// <param name="set2_shape">
        ///    1D <c>Tensor</c>, shape of a <c>SparseTensor</c>. <c>set2_shape[0...n-1]</c> must
        ///    be the same as the 1st <c>n-1</c> dimensions of <c>set1</c>, <c>result_shape[n]</c> is the
        ///    max set size across <c>n-1</c> dimensions.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DenseToSparseSetOperation'.
        /// </param>
        /// <param name="set_operation">
        ///    Optional argument
        /// </param>
        /// <param name="validate_indices">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    result_indices : 2D indices of a <c>SparseTensor</c>.
        ///    result_values : 1D values of a <c>SparseTensor</c>.
        ///    result_shape : 1D <c>Tensor</c> shape of a <c>SparseTensor</c>. <c>result_shape[0...n-1]</c> is
        ///    the same as the 1st <c>n-1</c> dimensions of <c>set1</c> and <c>set2</c>, <c>result_shape[n]</c>
        ///    is the max result set size across all <c>0...n-1</c> dimensions.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    See SetOperationOp::SetOperationFromContext for values of <c>set_operation</c>.
        ///    
        ///    Input <c>set2</c> is a <c>SparseTensor</c> represented by <c>set2_indices</c>, <c>set2_values</c>,
        ///    and <c>set2_shape</c>. For <c>set2</c> ranked <c>n</c>, 1st <c>n-1</c> dimensions must be the same
        ///    as <c>set1</c>. Dimension <c>n</c> contains values in a set, duplicates are allowed but
        ///    ignored.
        ///    
        ///    If <c>validate_indices</c> is <c>True</c>, this op validates the order and range of <c>set2</c>
        ///    indices.
        ///    
        ///    Output <c>result</c> is a <c>SparseTensor</c> represented by <c>result_indices</c>,
        ///    <c>result_values</c>, and <c>result_shape</c>. For <c>set1</c> and <c>set2</c> ranked <c>n</c>, this
        ///    has rank <c>n</c> and the same 1st <c>n-1</c> dimensions as <c>set1</c> and <c>set2</c>. The <c>nth</c>
        ///    dimension contains the result of <c>set_operation</c> applied to the corresponding
        ///    <c>[0...n-1]</c> dimension of <c>set</c>.
        /// </remarks>
        public static (Tensor result_indices, Tensor result_values, Tensor result_shape) dense_to_sparse_set_operation (Tensor set1, Tensor set2_indices, Tensor set2_values, Tensor set2_shape, string set_operation, bool? validate_indices = null, string name = "DenseToSparseSetOperation")
        {
            var dict = new Dictionary<string, object>();
            dict["set1"] = set1;
            dict["set2_indices"] = set2_indices;
            dict["set2_values"] = set2_values;
            dict["set2_shape"] = set2_shape;
            dict["set_operation"] = set_operation;
            if (validate_indices.HasValue)
                dict["validate_indices"] = validate_indices.Value;
            var op = _op_def_lib._apply_op_helper("DenseToSparseSetOperation", name: name, keywords: dict);
            int _idx = 0;
            var result_indices = op.outputs[_idx++];
            var result_values = op.outputs[_idx++];
            var result_shape = op.outputs[_idx++];
            return (result_indices, result_values, result_shape);
        }

        /// <summary>
        ///    DepthToSpace for tensors of type T.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DepthToSpace'.
        /// </param>
        /// <param name="block_size">
        ///    Optional argument
        ///    The size of the spatial block, same as in Space2Depth.
        /// </param>
        /// <param name="data_format">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Rearranges data from depth into blocks of spatial data.
        ///    This is the reverse transformation of SpaceToDepth. More specifically,
        ///    this op outputs a copy of the input tensor where values from the <c>depth</c>
        ///    dimension are moved in spatial blocks to the <c>height</c> and <c>width</c> dimensions.
        ///    The attr <c>block_size</c> indicates the input block size and how the data is moved.
        ///    
        ///    * Chunks of data of size <c>block_size * block_size</c> from depth are rearranged
        ///    into non-overlapping blocks of size <c>block_size x block_size</c>
        ///    * The width the output tensor is <c>input_depth * block_size</c>, whereas the
        ///    height is <c>input_height * block_size</c>.
        ///    * The Y, X coordinates within each block of the output image are determined
        ///    by the high order component of the input channel index.
        ///    * The depth of the input tensor must be divisible by
        ///    <c>block_size * block_size</c>.
        ///    
        ///    The <c>data_format</c> attr specifies the layout of the input and output tensors
        ///    with the following options:
        ///    "NHWC": <c>[ batch, height, width, channels ]</c>
        ///    "NCHW": <c>[ batch, channels, height, width ]</c>
        ///    "NCHW_VECT_C":
        ///    <c>qint8 [ batch, channels / 4, height, width, 4 ]</c>
        ///    
        ///    It is useful to consider the operation as transforming a 6-D Tensor.
        ///    e.g. for data_format = NHWC,
        ///    Each element in the input tensor can be specified via 6 coordinates,
        ///    ordered by decreasing memory layout significance as:
        ///    n,iY,iX,bY,bX,oC  (where n=batch index, iX, iY means X or Y coordinates
        ///    within the input image, bX, bY means coordinates
        ///    within the output block, oC means output channels).
        ///    The output would be the input transposed to the following layout:
        ///    n,iY,bY,iX,bX,oC
        ///    
        ///    This operation is useful for resizing the activations between convolutions
        ///    (but keeping all data), e.g. instead of pooling. It is also useful for training
        ///    purely convolutional models.
        ///    
        ///    For example, given an input of shape <c>[1, 1, 1, 4]</c>, data_format = "NHWC" and
        ///    block_size = 2:
        ///    
        ///   <code>
        ///    x = [[[[1, 2, 3, 4]]]]
        ///    
        ///   </code>
        ///    
        ///    This operation will output a tensor of shape <c>[1, 2, 2, 1]</c>:
        ///    
        ///   <code>
        ///    [[[[1], [2]],
        ///    [[3], [4]]]]
        ///   </code>
        ///    
        ///    Here, the input has a batch of 1 and each batch element has shape <c>[1, 1, 4]</c>,
        ///    the corresponding output will have 2x2 elements and will have a depth of
        ///    1 channel (1 = <c>4 / (block_size * block_size)</c>).
        ///    The output element shape is <c>[2, 2, 1]</c>.
        ///    
        ///    For an input tensor with larger depth, here of shape <c>[1, 1, 1, 12]</c>, e.g.
        ///    
        ///   <code>
        ///    x = [[[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]]]]
        ///   </code>
        ///    
        ///    This operation, for block size of 2, will return the following tensor of shape
        ///    <c>[1, 2, 2, 3]</c>
        ///    
        ///   <code>
        ///    [[[[1, 2, 3], [4, 5, 6]],
        ///    [[7, 8, 9], [10, 11, 12]]]]
        ///    
        ///   </code>
        ///    
        ///    Similarly, for the following input of shape <c>[1 2 2 4]</c>, and a block size of 2:
        ///    
        ///   <code>
        ///    x =  [[[[1, 2, 3, 4],
        ///    [5, 6, 7, 8]],
        ///    [[9, 10, 11, 12],
        ///    [13, 14, 15, 16]]]]
        ///   </code>
        ///    
        ///    the operator will return the following tensor of shape <c>[1 4 4 1]</c>:
        ///    
        ///   <code>
        ///    x = [[[ [1],   [2],  [5],  [6]],
        ///    [ [3],   [4],  [7],  [8]],
        ///    [ [9],  [10], [13],  [14]],
        ///    [ [11], [12], [15],  [16]]]]
        ///    
        ///   </code>
        /// </remarks>
        public static Tensor depth_to_space (Tensor input, int block_size, string data_format = null, string name = "DepthToSpace")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["block_size"] = block_size;
            if (data_format != null)
                dict["data_format"] = data_format;
            var op = _op_def_lib._apply_op_helper("DepthToSpace", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes a 2-D depthwise convolution given 4-D <c>input</c> and <c>filter</c> tensors.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="filter">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DepthwiseConv2dNative'.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    1-D of length 4.  The stride of the sliding window for each dimension
        ///    of <c>input</c>.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="data_format">
        ///    Specify the data format of the input and output data. With the
        ///    default format "NHWC", the data is stored in the order of:
        ///    [batch, height, width, channels].
        ///    Alternatively, the format could be "NCHW", the data storage order of:
        ///    [batch, channels, height, width].
        /// </param>
        /// <param name="dilations">
        ///    1-D tensor of length 4.  The dilation factor for each dimension of
        ///    <c>input</c>. If set to k &amp;gt; 1, there will be k-1 skipped cells between each filter
        ///    element on that dimension. The dimension order is determined by the value of
        ///    <c>data_format</c>, see above for details. Dilations in the batch and depth
        ///    dimensions must be 1.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given an input tensor of shape <c>[batch, in_height, in_width, in_channels]</c>
        ///    and a filter / kernel tensor of shape
        ///    <c>[filter_height, filter_width, in_channels, channel_multiplier]</c>, containing
        ///    <c>in_channels</c> convolutional filters of depth 1, <c>depthwise_conv2d</c> applies
        ///    a different filter to each input channel (expanding from 1 channel to
        ///    <c>channel_multiplier</c> channels for each), then concatenates the results
        ///    together. Thus, the output has <c>in_channels * channel_multiplier</c> channels.
        ///    
        ///   <code>
        ///    for k in 0..in_channels-1
        ///    for q in 0..channel_multiplier-1
        ///    output[b, i, j, k * channel_multiplier + q] =
        ///    sum_{di, dj} input[b, strides[1] * i + di, strides[2] * j + dj, k] *
        ///    filter[di, dj, k, q]
        ///   </code>
        ///    
        ///    Must have <c>strides[0] = strides[3] = 1</c>.  For the most common case of the same
        ///    horizontal and vertices strides, <c>strides = [1, stride, stride, 1]</c>.
        /// </remarks>
        public static Tensor depthwise_conv2d_native (Tensor input, Tensor filter, int[] strides, string padding, string data_format = null, int[] dilations = null, string name = "DepthwiseConv2dNative")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["filter"] = filter;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (data_format != null)
                dict["data_format"] = data_format;
            if (dilations != null)
                dict["dilations"] = dilations;
            var op = _op_def_lib._apply_op_helper("DepthwiseConv2dNative", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradients of depthwise convolution with respect to the filter.
        /// </summary>
        /// <param name="input">
        ///    4-D with shape based on <c>data_format</c>.  For example, if
        ///    <c>data_format</c> is 'NHWC' then <c>input</c> is a 4-D <c>[batch, in_height,
        ///    in_width, in_channels]</c> tensor.
        /// </param>
        /// <param name="filter_sizes">
        ///    An integer vector representing the tensor shape of <c>filter</c>,
        ///    where <c>filter</c> is a 4-D
        ///    <c>[filter_height, filter_width, in_channels, depthwise_multiplier]</c> tensor.
        /// </param>
        /// <param name="out_backprop">
        ///    4-D with shape  based on <c>data_format</c>.
        ///    For example, if <c>data_format</c> is 'NHWC' then
        ///    out_backprop shape is <c>[batch, out_height, out_width, out_channels]</c>.
        ///    Gradients w.r.t. the output of the convolution.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DepthwiseConv2dNativeBackpropFilter'.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    The stride of the sliding window for each dimension of the input
        ///    of the convolution.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="data_format">
        ///    Specify the data format of the input and output data. With the
        ///    default format "NHWC", the data is stored in the order of:
        ///    [batch, height, width, channels].
        ///    Alternatively, the format could be "NCHW", the data storage order of:
        ///    [batch, channels, height, width].
        /// </param>
        /// <param name="dilations">
        ///    1-D tensor of length 4.  The dilation factor for each dimension of
        ///    <c>input</c>. If set to k &amp;gt; 1, there will be k-1 skipped cells between each filter
        ///    element on that dimension. The dimension order is determined by the value of
        ///    <c>data_format</c>, see above for details. Dilations in the batch and depth
        ///    dimensions must be 1.
        /// </param>
        /// <returns>
        ///    4-D with shape
        ///    <c>[filter_height, filter_width, in_channels, out_channels]</c>.  Gradient w.r.t.
        ///    the <c>filter</c> input of the convolution.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor depthwise_conv2d_native_backprop_filter (Tensor input, Tensor filter_sizes, Tensor out_backprop, int[] strides, string padding, string data_format = null, int[] dilations = null, string name = "DepthwiseConv2dNativeBackpropFilter")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["filter_sizes"] = filter_sizes;
            dict["out_backprop"] = out_backprop;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (data_format != null)
                dict["data_format"] = data_format;
            if (dilations != null)
                dict["dilations"] = dilations;
            var op = _op_def_lib._apply_op_helper("DepthwiseConv2dNativeBackpropFilter", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradients of depthwise convolution with respect to the input.
        /// </summary>
        /// <param name="input_sizes">
        ///    An integer vector representing the shape of <c>input</c>, based
        ///    on <c>data_format</c>.  For example, if <c>data_format</c> is 'NHWC' then
        ///    <c>input</c> is a 4-D <c>[batch, height, width, channels]</c> tensor.
        /// </param>
        /// <param name="filter">
        ///    4-D with shape
        ///    <c>[filter_height, filter_width, in_channels, depthwise_multiplier]</c>.
        /// </param>
        /// <param name="out_backprop">
        ///    4-D with shape  based on <c>data_format</c>.
        ///    For example, if <c>data_format</c> is 'NHWC' then
        ///    out_backprop shape is <c>[batch, out_height, out_width, out_channels]</c>.
        ///    Gradients w.r.t. the output of the convolution.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DepthwiseConv2dNativeBackpropInput'.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    The stride of the sliding window for each dimension of the input
        ///    of the convolution.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="data_format">
        ///    Specify the data format of the input and output data. With the
        ///    default format "NHWC", the data is stored in the order of:
        ///    [batch, height, width, channels].
        ///    Alternatively, the format could be "NCHW", the data storage order of:
        ///    [batch, channels, height, width].
        /// </param>
        /// <param name="dilations">
        ///    1-D tensor of length 4.  The dilation factor for each dimension of
        ///    <c>input</c>. If set to k &amp;gt; 1, there will be k-1 skipped cells between each filter
        ///    element on that dimension. The dimension order is determined by the value of
        ///    <c>data_format</c>, see above for details. Dilations in the batch and depth
        ///    dimensions must be 1.
        /// </param>
        /// <returns>
        ///    4-D with shape according to <c>data_format</c>.  For example, if
        ///    <c>data_format</c> is 'NHWC', output shape is <c>[batch, in_height,
        ///    in_width, in_channels]</c>.  Gradient w.r.t. the input of the
        ///    convolution.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor depthwise_conv2d_native_backprop_input (Tensor input_sizes, Tensor filter, Tensor out_backprop, int[] strides, string padding, string data_format = null, int[] dilations = null, string name = "DepthwiseConv2dNativeBackpropInput")
        {
            var dict = new Dictionary<string, object>();
            dict["input_sizes"] = input_sizes;
            dict["filter"] = filter;
            dict["out_backprop"] = out_backprop;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (data_format != null)
                dict["data_format"] = data_format;
            if (dilations != null)
                dict["dilations"] = dilations;
            var op = _op_def_lib._apply_op_helper("DepthwiseConv2dNativeBackpropInput", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Dequantize the 'input' tensor into a float Tensor.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="min_range">
        ///    The minimum scalar value possibly produced for the input.
        /// </param>
        /// <param name="max_range">
        ///    The maximum scalar value possibly produced for the input.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Dequantize'.
        /// </param>
        /// <param name="mode">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    [min_range, max_range] are scalar floats that specify the range for
        ///    the 'input' data. The 'mode' attribute controls exactly which calculations are
        ///    used to convert the float values to their quantized equivalents.
        ///    
        ///    In 'MIN_COMBINED' mode, each value of the tensor will undergo the following:
        ///    
        ///   <code>
        ///    if T == qint8, in[i] += (range(T) + 1)/ 2.0
        ///    out[i] = min_range + (in[i]* (max_range - min_range) / range(T))
        ///   </code>
        ///    here <c>range(T) = numeric_limits&amp;lt;T&amp;gt;::max() - numeric_limits&amp;lt;T&amp;gt;::min()</c>
        ///    
        ///    *MIN_COMBINED Mode Example*
        ///    
        ///    If the input comes from a QuantizedRelu6, the output type is
        ///    quint8 (range of 0-255) but the possible range of QuantizedRelu6 is
        ///    0-6.  The min_range and max_range values are therefore 0.0 and 6.0.
        ///    Dequantize on quint8 will take each value, cast to float, and multiply
        ///    by 6 / 255.
        ///    Note that if quantizedtype is qint8, the operation will additionally add
        ///    each value by 128 prior to casting.
        ///    
        ///    If the mode is 'MIN_FIRST', then this approach is used:
        ///    
        ///   <code>
        ///    num_discrete_values = 1 &amp;lt;&amp;lt; (# of bits in T)
        ///    range_adjust = num_discrete_values / (num_discrete_values - 1)
        ///    range = (range_max - range_min) * range_adjust
        ///    range_scale = range / num_discrete_values
        ///    const double offset_input = static_cast&amp;lt;double&amp;gt;(input) - lowest_quantized;
        ///    result = range_min + ((input - numeric_limits&amp;lt;T&amp;gt;::min()) * range_scale)
        ///   </code>
        ///    
        ///    *SCALED mode Example*
        ///    
        ///    <c>SCALED</c> mode matches the quantization approach used in
        ///    <c>QuantizeAndDequantize{V2|V3}</c>.
        ///    
        ///    If the mode is <c>SCALED</c>, we do not use the full range of the output type,
        ///    choosing to elide the lowest possible value for symmetry (e.g., output range is
        ///    -127 to 127, not -128 to 127 for signed 8 bit quantization), so that 0.0 maps to
        ///    0.
        ///    
        ///    We first find the range of values in our tensor. The
        ///    range we use is always centered on 0, so we find m such that
        ///   <code>
        ///    m = max(abs(input_min), abs(input_max))
        ///   </code>
        ///    
        ///    Our input tensor range is then <c>[-m, m]</c>.
        ///    
        ///    Next, we choose our fixed-point quantization buckets, <c>[min_fixed, max_fixed]</c>.
        ///    If T is signed, this is
        ///   <code>
        ///    num_bits = sizeof(T) * 8
        ///    [min_fixed, max_fixed] =
        ///    [-(1 &amp;lt;&amp;lt; (num_bits - 1) - 1), (1 &amp;lt;&amp;lt; (num_bits - 1)) - 1]
        ///   </code>
        ///    
        ///    Otherwise, if T is unsigned, the fixed-point range is
        ///   <code>
        ///    [min_fixed, max_fixed] = [0, (1 &amp;lt;&amp;lt; num_bits) - 1]
        ///   </code>
        ///    
        ///    From this we compute our scaling factor, s:
        ///   <code>
        ///    s = (2 * m) / (max_fixed - min_fixed)
        ///   </code>
        ///    
        ///    Now we can dequantize the elements of our tensor:
        ///   <code>
        ///    result = input * s
        ///   </code>
        /// </remarks>
        public static Tensor dequantize (Tensor input, Tensor min_range, Tensor max_range, string mode = null, string name = "Dequantize")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["min_range"] = min_range;
            dict["max_range"] = max_range;
            if (mode != null)
                dict["mode"] = mode;
            var op = _op_def_lib._apply_op_helper("Dequantize", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Converts the given variant tensor to an iterator and stores it in the given resource.
        /// </summary>
        /// <param name="resource_handle">
        ///    A handle to an iterator resource.
        /// </param>
        /// <param name="serialized">
        ///    A variant tensor storing the state of the iterator contained in the
        ///    resource.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DeserializeIterator'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation deserialize_iterator (Tensor resource_handle, Tensor serialized, string name = "DeserializeIterator")
        {
            var dict = new Dictionary<string, object>();
            dict["resource_handle"] = resource_handle;
            dict["serialized"] = serialized;
            var op = _op_def_lib._apply_op_helper("DeserializeIterator", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Deserialize and concatenate <c>SparseTensors</c> from a serialized minibatch.
        /// </summary>
        /// <param name="serialized_sparse">
        ///    2-D, The <c>N</c> serialized <c>SparseTensor</c> objects.
        ///    Must have 3 columns.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DeserializeManySparse'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The <c>dtype</c> of the serialized <c>SparseTensor</c> objects.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    sparse_indices :
        ///    sparse_values :
        ///    sparse_shape :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    The input <c>serialized_sparse</c> must be a string matrix of shape <c>[N x 3]</c> where
        ///    <c>N</c> is the minibatch size and the rows correspond to packed outputs of
        ///    <c>SerializeSparse</c>.  The ranks of the original <c>SparseTensor</c> objects
        ///    must all match.  When the final <c>SparseTensor</c> is created, it has rank one
        ///    higher than the ranks of the incoming <c>SparseTensor</c> objects
        ///    (they have been concatenated along a new row dimension).
        ///    
        ///    The output <c>SparseTensor</c> object's shape values for all dimensions but the
        ///    first are the max across the input <c>SparseTensor</c> objects' shape values
        ///    for the corresponding dimensions.  Its first shape value is <c>N</c>, the minibatch
        ///    size.
        ///    
        ///    The input <c>SparseTensor</c> objects' indices are assumed ordered in
        ///    standard lexicographic order.  If this is not the case, after this
        ///    step run <c>SparseReorder</c> to restore index ordering.
        ///    
        ///    For example, if the serialized input is a <c>[2 x 3]</c> matrix representing two
        ///    original <c>SparseTensor</c> objects:
        ///    
        ///    index = [ 0]
        ///    [10]
        ///    [20]
        ///    values = [1, 2, 3]
        ///    shape = [50]
        ///    
        ///    and
        ///    
        ///    index = [ 2]
        ///    [10]
        ///    values = [4, 5]
        ///    shape = [30]
        ///    
        ///    then the final deserialized <c>SparseTensor</c> will be:
        ///    
        ///    index = [0  0]
        ///    [0 10]
        ///    [0 20]
        ///    [1  2]
        ///    [1 10]
        ///    values = [1, 2, 3, 4, 5]
        ///    shape = [2 50]
        /// </remarks>
        public static (Tensor sparse_indices, Tensor sparse_values, Tensor sparse_shape) deserialize_many_sparse (Tensor serialized_sparse, TF_DataType dtype, string name = "DeserializeManySparse")
        {
            var dict = new Dictionary<string, object>();
            dict["serialized_sparse"] = serialized_sparse;
            dict["dtype"] = dtype;
            var op = _op_def_lib._apply_op_helper("DeserializeManySparse", name: name, keywords: dict);
            int _idx = 0;
            var sparse_indices = op.outputs[_idx++];
            var sparse_values = op.outputs[_idx++];
            var sparse_shape = op.outputs[_idx++];
            return (sparse_indices, sparse_values, sparse_shape);
        }

        /// <summary>
        ///    Deserialize <c>SparseTensor</c> objects.
        /// </summary>
        /// <param name="serialized_sparse">
        ///    The serialized <c>SparseTensor</c> objects. The last dimension
        ///    must have 3 columns.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DeserializeSparse'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The <c>dtype</c> of the serialized <c>SparseTensor</c> objects.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    sparse_indices :
        ///    sparse_values :
        ///    sparse_shape :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    The input <c>serialized_sparse</c> must have the shape <c>[?, ?, ..., ?, 3]</c> where
        ///    the last dimension stores serialized <c>SparseTensor</c> objects and the other N
        ///    dimensions (N &amp;gt;= 0) correspond to a batch. The ranks of the original
        ///    <c>SparseTensor</c> objects must all match. When the final <c>SparseTensor</c> is
        ///    created, its rank is the rank of the incoming <c>SparseTensor</c> objects plus N;
        ///    the sparse tensors have been concatenated along new dimensions, one for each
        ///    batch.
        ///    
        ///    The output <c>SparseTensor</c> object's shape values for the original dimensions
        ///    are the max across the input <c>SparseTensor</c> objects' shape values for the
        ///    corresponding dimensions. The new dimensions match the size of the batch.
        ///    
        ///    The input <c>SparseTensor</c> objects' indices are assumed ordered in
        ///    standard lexicographic order.  If this is not the case, after this
        ///    step run <c>SparseReorder</c> to restore index ordering.
        ///    
        ///    For example, if the serialized input is a <c>[2 x 3]</c> matrix representing two
        ///    original <c>SparseTensor</c> objects:
        ///    
        ///    index = [ 0]
        ///    [10]
        ///    [20]
        ///    values = [1, 2, 3]
        ///    shape = [50]
        ///    
        ///    and
        ///    
        ///    index = [ 2]
        ///    [10]
        ///    values = [4, 5]
        ///    shape = [30]
        ///    
        ///    then the final deserialized <c>SparseTensor</c> will be:
        ///    
        ///    index = [0  0]
        ///    [0 10]
        ///    [0 20]
        ///    [1  2]
        ///    [1 10]
        ///    values = [1, 2, 3, 4, 5]
        ///    shape = [2 50]
        /// </remarks>
        public static (Tensor sparse_indices, Tensor sparse_values, Tensor sparse_shape) deserialize_sparse (Tensor serialized_sparse, TF_DataType dtype, string name = "DeserializeSparse")
        {
            var dict = new Dictionary<string, object>();
            dict["serialized_sparse"] = serialized_sparse;
            dict["dtype"] = dtype;
            var op = _op_def_lib._apply_op_helper("DeserializeSparse", name: name, keywords: dict);
            int _idx = 0;
            var sparse_indices = op.outputs[_idx++];
            var sparse_values = op.outputs[_idx++];
            var sparse_shape = op.outputs[_idx++];
            return (sparse_indices, sparse_values, sparse_shape);
        }

        /// <summary>
        ///    Deletes the resource specified by the handle.
        /// </summary>
        /// <param name="resource">
        ///    handle to the resource to delete.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DestroyResourceOp'.
        /// </param>
        /// <param name="ignore_lookup_error">
        ///    whether to ignore the error when the resource
        ///    doesn't exist.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    All subsequent operations using the resource will result in a NotFound
        ///    error status.
        /// </remarks>
        public static Operation destroy_resource_op (Tensor resource, bool? ignore_lookup_error = null, string name = "DestroyResourceOp")
        {
            var dict = new Dictionary<string, object>();
            dict["resource"] = resource;
            if (ignore_lookup_error.HasValue)
                dict["ignore_lookup_error"] = ignore_lookup_error.Value;
            var op = _op_def_lib._apply_op_helper("DestroyResourceOp", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Destroys the temporary variable and returns its final value.
        /// </summary>
        /// <param name="referecne">
        ///    A reference to the temporary variable tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DestroyTemporaryVariable'.
        /// </param>
        /// <param name="var_name">
        ///    Optional argument
        ///    Name of the temporary variable, usually the name of the matching
        ///    'TemporaryVariable' op.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Sets output to the value of the Tensor pointed to by 'ref', then destroys
        ///    the temporary variable called 'var_name'.
        ///    All other uses of 'ref' *must* have executed before this op.
        ///    This is typically achieved by chaining the ref through each assign op, or by
        ///    using control dependencies.
        ///    
        ///    Outputs the final value of the tensor pointed to by 'ref'.
        /// </remarks>
        public static Tensor destroy_temporary_variable (Tensor referecne, string var_name, string name = "DestroyTemporaryVariable")
        {
            var dict = new Dictionary<string, object>();
            dict["ref"] = referecne;
            dict["var_name"] = var_name;
            var op = _op_def_lib._apply_op_helper("DestroyTemporaryVariable", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns a diagonal tensor with a given diagonal values.
        /// </summary>
        /// <param name="diagonal">
        ///    Rank k tensor where k is at most 1.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Diag'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given a <c>diagonal</c>, this operation returns a tensor with the <c>diagonal</c> and
        ///    everything else padded with zeros. The diagonal is computed as follows:
        ///    
        ///    Assume <c>diagonal</c> has dimensions [D1,..., Dk], then the output is a tensor of
        ///    rank 2k with dimensions [D1,..., Dk, D1,..., Dk] where:
        ///    
        ///    <c>output[i1,..., ik, i1,..., ik] = diagonal[i1, ..., ik]</c> and 0 everywhere else.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # 'diagonal' is [1, 2, 3, 4]
        ///    tf.diag(diagonal) ==&amp;gt; [[1, 0, 0, 0]
        ///    [0, 2, 0, 0]
        ///    [0, 0, 3, 0]
        ///    [0, 0, 0, 4]]
        ///   </code>
        /// </remarks>
        public static Tensor diag (Tensor diagonal, string name = "Diag")
        {
            var dict = new Dictionary<string, object>();
            dict["diagonal"] = diagonal;
            var op = _op_def_lib._apply_op_helper("Diag", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the diagonal part of the tensor.
        /// </summary>
        /// <param name="input">
        ///    Rank k tensor where k is even and not zero.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DiagPart'.
        /// </param>
        /// <returns>
        ///    The extracted diagonal.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation returns a tensor with the <c>diagonal</c> part
        ///    of the <c>input</c>. The <c>diagonal</c> part is computed as follows:
        ///    
        ///    Assume <c>input</c> has dimensions <c>[D1,..., Dk, D1,..., Dk]</c>, then the output is a
        ///    tensor of rank <c>k</c> with dimensions <c>[D1,..., Dk]</c> where:
        ///    
        ///    <c>diagonal[i1,..., ik] = input[i1, ..., ik, i1,..., ik]</c>.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # 'input' is [[1, 0, 0, 0]
        ///    [0, 2, 0, 0]
        ///    [0, 0, 3, 0]
        ///    [0, 0, 0, 4]]
        ///    
        ///    tf.diag_part(input) ==&amp;gt; [1, 2, 3, 4]
        ///   </code>
        /// </remarks>
        public static Tensor diag_part (Tensor input, string name = "DiagPart")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("DiagPart", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes Psi, the derivative of Lgamma (the log of the absolute value of
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Digamma'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    <c>Gamma(x)</c>), element-wise.
        /// </remarks>
        public static Tensor digamma (Tensor x, string name = "Digamma")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Digamma", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the grayscale dilation of 4-D <c>input</c> and 3-D <c>filter</c> tensors.
        /// </summary>
        /// <param name="input">
        ///    4-D with shape <c>[batch, in_height, in_width, depth]</c>.
        /// </param>
        /// <param name="filter">
        ///    3-D with shape <c>[filter_height, filter_width, depth]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Dilation2D'.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    The stride of the sliding window for each dimension of the input
        ///    tensor. Must be: <c>[1, stride_height, stride_width, 1]</c>.
        /// </param>
        /// <param name="rates">
        ///    Optional argument
        ///    The input stride for atrous morphological dilation. Must be:
        ///    <c>[1, rate_height, rate_width, 1]</c>.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <returns>
        ///    4-D with shape <c>[batch, out_height, out_width, depth]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The <c>input</c> tensor has shape <c>[batch, in_height, in_width, depth]</c> and the
        ///    <c>filter</c> tensor has shape <c>[filter_height, filter_width, depth]</c>, i.e., each
        ///    input channel is processed independently of the others with its own structuring
        ///    function. The <c>output</c> tensor has shape
        ///    <c>[batch, out_height, out_width, depth]</c>. The spatial dimensions of the output
        ///    tensor depend on the <c>padding</c> algorithm. We currently only support the default
        ///    "NHWC" <c>data_format</c>.
        ///    
        ///    In detail, the grayscale morphological 2-D dilation is the max-sum correlation
        ///    (for consistency with <c>conv2d</c>, we use unmirrored filters):
        ///    
        ///    output[b, y, x, c] =
        ///    max_{dy, dx} input[b,
        ///    strides[1] * y + rates[1] * dy,
        ///    strides[2] * x + rates[2] * dx,
        ///    c] +
        ///    filter[dy, dx, c]
        ///    
        ///    Max-pooling is a special case when the filter has size equal to the pooling
        ///    kernel size and contains all zeros.
        ///    
        ///    Note on duality: The dilation of <c>input</c> by the <c>filter</c> is equal to the
        ///    negation of the erosion of <c>-input</c> by the reflected <c>filter</c>.
        /// </remarks>
        public static Tensor dilation2d (Tensor input, Tensor filter, int[] strides, int[] rates, string padding, string name = "Dilation2D")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["filter"] = filter;
            dict["strides"] = strides;
            dict["rates"] = rates;
            dict["padding"] = padding;
            var op = _op_def_lib._apply_op_helper("Dilation2D", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradient of morphological 2-D dilation with respect to the filter.
        /// </summary>
        /// <param name="input">
        ///    4-D with shape <c>[batch, in_height, in_width, depth]</c>.
        /// </param>
        /// <param name="filter">
        ///    3-D with shape <c>[filter_height, filter_width, depth]</c>.
        /// </param>
        /// <param name="out_backprop">
        ///    4-D with shape <c>[batch, out_height, out_width, depth]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Dilation2DBackpropFilter'.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    1-D of length 4. The stride of the sliding window for each dimension of
        ///    the input tensor. Must be: <c>[1, stride_height, stride_width, 1]</c>.
        /// </param>
        /// <param name="rates">
        ///    Optional argument
        ///    1-D of length 4. The input stride for atrous morphological dilation.
        ///    Must be: <c>[1, rate_height, rate_width, 1]</c>.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <returns>
        ///    3-D with shape <c>[filter_height, filter_width, depth]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor dilation2d_backprop_filter (Tensor input, Tensor filter, Tensor out_backprop, int[] strides, int[] rates, string padding, string name = "Dilation2DBackpropFilter")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["filter"] = filter;
            dict["out_backprop"] = out_backprop;
            dict["strides"] = strides;
            dict["rates"] = rates;
            dict["padding"] = padding;
            var op = _op_def_lib._apply_op_helper("Dilation2DBackpropFilter", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradient of morphological 2-D dilation with respect to the input.
        /// </summary>
        /// <param name="input">
        ///    4-D with shape <c>[batch, in_height, in_width, depth]</c>.
        /// </param>
        /// <param name="filter">
        ///    3-D with shape <c>[filter_height, filter_width, depth]</c>.
        /// </param>
        /// <param name="out_backprop">
        ///    4-D with shape <c>[batch, out_height, out_width, depth]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Dilation2DBackpropInput'.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    1-D of length 4. The stride of the sliding window for each dimension of
        ///    the input tensor. Must be: <c>[1, stride_height, stride_width, 1]</c>.
        /// </param>
        /// <param name="rates">
        ///    Optional argument
        ///    1-D of length 4. The input stride for atrous morphological dilation.
        ///    Must be: <c>[1, rate_height, rate_width, 1]</c>.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <returns>
        ///    4-D with shape <c>[batch, in_height, in_width, depth]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor dilation2d_backprop_input (Tensor input, Tensor filter, Tensor out_backprop, int[] strides, int[] rates, string padding, string name = "Dilation2DBackpropInput")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["filter"] = filter;
            dict["out_backprop"] = out_backprop;
            dict["strides"] = strides;
            dict["rates"] = rates;
            dict["padding"] = padding;
            var op = _op_def_lib._apply_op_helper("Dilation2DBackpropInput", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns x / y element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Div'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    *NOTE*: <c>Div</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor div (Tensor x, Tensor y, string name = "Div")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("Div", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns 0 if the denominator is zero.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DivNoNan'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    
        ///    *NOTE*: <c>DivNoNan</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor div_no_nan (Tensor x, Tensor y, string name = "DivNoNan")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("DivNoNan", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Draw bounding boxes on a batch of images.
        /// </summary>
        /// <param name="images">
        ///    4-D with shape <c>[batch, height, width, depth]</c>. A batch of images.
        /// </param>
        /// <param name="boxes">
        ///    3-D with shape <c>[batch, num_bounding_boxes, 4]</c> containing bounding
        ///    boxes.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DrawBoundingBoxes'.
        /// </param>
        /// <returns>
        ///    4-D with the same shape as <c>images</c>. The batch of input images with
        ///    bounding boxes drawn on the images.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Outputs a copy of <c>images</c> but draws on top of the pixels zero or more bounding
        ///    boxes specified by the locations in <c>boxes</c>. The coordinates of the each
        ///    bounding box in <c>boxes</c> are encoded as <c>[y_min, x_min, y_max, x_max]</c>. The
        ///    bounding box coordinates are floats in <c>[0.0, 1.0]</c> relative to the width and
        ///    height of the underlying image.
        ///    
        ///    For example, if an image is 100 x 200 pixels (height x width) and the bounding
        ///    box is <c>[0.1, 0.2, 0.5, 0.9]</c>, the upper-left and bottom-right coordinates of
        ///    the bounding box will be <c>(40, 10)</c> to <c>(180, 50)</c> (in (x,y) coordinates).
        ///    
        ///    Parts of the bounding box may fall outside the image.
        /// </remarks>
        public static Tensor draw_bounding_boxes (Tensor images, Tensor boxes, string name = "DrawBoundingBoxes")
        {
            var dict = new Dictionary<string, object>();
            dict["images"] = images;
            dict["boxes"] = boxes;
            var op = _op_def_lib._apply_op_helper("DrawBoundingBoxes", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Partitions <c>data</c> into <c>num_partitions</c> tensors using indices from <c>partitions</c>.
        /// </summary>
        /// <param name="data">
        /// </param>
        /// <param name="partitions">
        ///    Any shape.  Indices in the range <c>[0, num_partitions)</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DynamicPartition'.
        /// </param>
        /// <param name="num_partitions">
        ///    Optional argument
        ///    The number of partitions to output.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    For each index tuple <c>js</c> of size <c>partitions.ndim</c>, the slice <c>data[js, ...]</c>
        ///    becomes part of <c>outputs[partitions[js]]</c>.  The slices with <c>partitions[js] = i</c>
        ///    are placed in <c>outputs[i]</c> in lexicographic order of <c>js</c>, and the first
        ///    dimension of <c>outputs[i]</c> is the number of entries in <c>partitions</c> equal to <c>i</c>.
        ///    In detail,
        ///    
        ///   <code>
        ///    outputs[i].shape = [sum(partitions == i)] + data.shape[partitions.ndim:]
        ///    
        ///    outputs[i] = pack([data[js, ...] for js if partitions[js] == i])
        ///   </code>
        ///    
        ///    <c>data.shape</c> must start with <c>partitions.shape</c>.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # Scalar partitions.
        ///    partitions = 1
        ///    num_partitions = 2
        ///    data = [10, 20]
        ///    outputs[0] = []  # Empty with shape [0, 2]
        ///    outputs[1] = [[10, 20]]
        ///    
        ///    # Vector partitions.
        ///    partitions = [0, 0, 1, 1, 0]
        ///    num_partitions = 2
        ///    data = [10, 20, 30, 40, 50]
        ///    outputs[0] = [10, 20, 50]
        ///    outputs[1] = [30, 40]
        ///   </code>
        ///    
        ///    See <c>dynamic_stitch</c> for an example on how to merge partitions back.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src="https://www.tensorflow.org/images/DynamicPartition.png" alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Tensor[] dynamic_partition (Tensor data, Tensor partitions, int num_partitions, string name = "DynamicPartition")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            dict["partitions"] = partitions;
            dict["num_partitions"] = num_partitions;
            var op = _op_def_lib._apply_op_helper("DynamicPartition", name: name, keywords: dict);
            int _idx = 0;
            var outputs = Enumerable.Range(0, op.OutputListLength("outputs")).Select(_ => op.outputs[_idx++]).ToArray();
            return (outputs);
        }

        /// <summary>
        ///    Interleave the values from the <c>data</c> tensors into a single tensor.
        /// </summary>
        /// <param name="indices">
        /// </param>
        /// <param name="data">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'DynamicStitch'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Builds a merged tensor such that
        ///    
        ///   <code>
        ///    merged[indices[m][i, ..., j], ...] = data[m][i, ..., j, ...]
        ///   </code>
        ///    
        ///    For example, if each <c>indices[m]</c> is scalar or vector, we have
        ///    
        ///   <code>
        ///    # Scalar indices:
        ///    merged[indices[m], ...] = data[m][...]
        ///    
        ///    # Vector indices:
        ///    merged[indices[m][i], ...] = data[m][i, ...]
        ///   </code>
        ///    
        ///    Each <c>data[i].shape</c> must start with the corresponding <c>indices[i].shape</c>,
        ///    and the rest of <c>data[i].shape</c> must be constant w.r.t. <c>i</c>.  That is, we
        ///    must have <c>data[i].shape = indices[i].shape + constant</c>.  In terms of this
        ///    <c>constant</c>, the output shape is
        ///    
        ///    merged.shape = [max(indices)] + constant
        ///    
        ///    Values are merged in order, so if an index appears in both <c>indices[m][i]</c> and
        ///    <c>indices[n][j]</c> for <c>(m,i) &amp;lt; (n,j)</c> the slice <c>data[n][j]</c> will appear in the
        ///    merged result. If you do not need this guarantee, ParallelDynamicStitch might
        ///    perform better on some devices.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    indices[0] = 6
        ///    indices[1] = [4, 1]
        ///    indices[2] = [[5, 2], [0, 3]]
        ///    data[0] = [61, 62]
        ///    data[1] = [[41, 42], [11, 12]]
        ///    data[2] = [[[51, 52], [21, 22]], [[1, 2], [31, 32]]]
        ///    merged = [[1, 2], [11, 12], [21, 22], [31, 32], [41, 42],
        ///    [51, 52], [61, 62]]
        ///   </code>
        ///    
        ///    This method can be used to merge partitions created by <c>dynamic_partition</c>
        ///    as illustrated on the following example:
        ///    
        ///   <code>
        ///    # Apply function (increments x_i) on elements for which a certain condition
        ///    # apply (x_i != -1 in this example).
        ///    x=tf.constant([0.1, -1., 5.2, 4.3, -1., 7.4])
        ///    condition_mask=tf.not_equal(x,tf.constant(-1.))
        ///    partitioned_data = tf.dynamic_partition(
        ///    x, tf.cast(condition_mask, tf.int32) , 2)
        ///    partitioned_data[1] = partitioned_data[1] + 1.0
        ///    condition_indices = tf.dynamic_partition(
        ///    tf.range(tf.shape(x)[0]), tf.cast(condition_mask, tf.int32) , 2)
        ///    x = tf.dynamic_stitch(condition_indices, partitioned_data)
        ///    # Here x=[1.1, -1., 6.2, 5.3, -1, 8.4], the -1. values remain
        ///    # unchanged.
        ///   </code>
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src="https://www.tensorflow.org/images/DynamicStitch.png" alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Tensor dynamic_stitch (Tensor[] indices, Tensor[] data, string name = "DynamicStitch")
        {
            var dict = new Dictionary<string, object>();
            dict["indices"] = indices;
            dict["data"] = data;
            var op = _op_def_lib._apply_op_helper("DynamicStitch", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the (possibly normalized) Levenshtein Edit Distance.
        /// </summary>
        /// <param name="hypothesis_indices">
        ///    The indices of the hypothesis list SparseTensor.
        ///    This is an N x R int64 matrix.
        /// </param>
        /// <param name="hypothesis_values">
        ///    The values of the hypothesis list SparseTensor.
        ///    This is an N-length vector.
        /// </param>
        /// <param name="hypothesis_shape">
        ///    The shape of the hypothesis list SparseTensor.
        ///    This is an R-length vector.
        /// </param>
        /// <param name="truth_indices">
        ///    The indices of the truth list SparseTensor.
        ///    This is an M x R int64 matrix.
        /// </param>
        /// <param name="truth_values">
        ///    The values of the truth list SparseTensor.
        ///    This is an M-length vector.
        /// </param>
        /// <param name="truth_shape">
        ///    truth indices, vector.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'EditDistance'.
        /// </param>
        /// <param name="normalize">
        ///    boolean (if true, edit distances are normalized by length of truth).
        ///    
        ///    The output is:
        /// </param>
        /// <returns>
        ///    A dense float tensor with rank R - 1.
        ///    
        ///    For the example input:
        ///    
        ///    // hypothesis represents a 2x1 matrix with variable-length values:
        ///    //   (0,0) = ["a"]
        ///    //   (1,0) = ["b"]
        ///    hypothesis_indices = [[0, 0, 0],
        ///    [1, 0, 0]]
        ///    hypothesis_values = ["a", "b"]
        ///    hypothesis_shape = [2, 1, 1]
        ///    
        ///    // truth represents a 2x2 matrix with variable-length values:
        ///    //   (0,0) = []
        ///    //   (0,1) = ["a"]
        ///    //   (1,0) = ["b", "c"]
        ///    //   (1,1) = ["a"]
        ///    truth_indices = [[0, 1, 0],
        ///    [1, 0, 0],
        ///    [1, 0, 1],
        ///    [1, 1, 0]]
        ///    truth_values = ["a", "b", "c", "a"]
        ///    truth_shape = [2, 2, 2]
        ///    normalize = true
        ///    
        ///    The output will be:
        ///    
        ///    // output is a 2x2 matrix with edit distances normalized by truth lengths.
        ///    output = [[inf, 1.0],  // (0,0): no truth, (0,1): no hypothesis
        ///    [0.5, 1.0]]  // (1,0): addition, (1,1): no hypothesis
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The inputs are variable-length sequences provided by SparseTensors
        ///    (hypothesis_indices, hypothesis_values, hypothesis_shape)
        ///    and
        ///    (truth_indices, truth_values, truth_shape).
        ///    
        ///    The inputs are:
        /// </remarks>
        public static Tensor edit_distance (Tensor hypothesis_indices, Tensor hypothesis_values, Tensor hypothesis_shape, Tensor truth_indices, Tensor truth_values, Tensor truth_shape, bool? normalize = null, string name = "EditDistance")
        {
            var dict = new Dictionary<string, object>();
            dict["hypothesis_indices"] = hypothesis_indices;
            dict["hypothesis_values"] = hypothesis_values;
            dict["hypothesis_shape"] = hypothesis_shape;
            dict["truth_indices"] = truth_indices;
            dict["truth_values"] = truth_values;
            dict["truth_shape"] = truth_shape;
            if (normalize.HasValue)
                dict["normalize"] = normalize.Value;
            var op = _op_def_lib._apply_op_helper("EditDistance", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes exponential linear: <c>exp(features) - 1</c> if &amp;lt; 0, <c>features</c> otherwise.
        /// </summary>
        /// <param name="features">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Elu'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    See [Fast and Accurate Deep Network Learning by Exponential Linear Units (ELUs)
        ///    ](http://arxiv.org/abs/1511.07289)
        /// </remarks>
        public static Tensor elu (Tensor features, string name = "Elu")
        {
            var dict = new Dictionary<string, object>();
            dict["features"] = features;
            var op = _op_def_lib._apply_op_helper("Elu", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes gradients for the exponential linear (Elu) operation.
        /// </summary>
        /// <param name="gradients">
        ///    The backpropagated gradients to the corresponding Elu operation.
        /// </param>
        /// <param name="outputs">
        ///    The outputs of the corresponding Elu operation.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'EluGrad'.
        /// </param>
        /// <returns>
        ///    The gradients: <c>gradients * (outputs + 1)</c> if outputs &amp;lt; 0,
        ///    <c>gradients</c> otherwise.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor elu_grad (Tensor gradients, Tensor outputs, string name = "EluGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["gradients"] = gradients;
            dict["outputs"] = outputs;
            var op = _op_def_lib._apply_op_helper("EluGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a tensor with the given shape.
        ///    
        ///    This operation creates a tensor of <c>shape</c> and <c>dtype</c>.
        /// </summary>
        /// <param name="shape">
        ///    1-D. Represents the shape of the output tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Empty'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        /// </param>
        /// <param name="init">
        ///    If True, initialize the returned tensor with the default value of dtype.  Otherwise, the implementation is free not to initializethe tensor's content.
        /// </param>
        /// <returns>
        ///    A <c>Tensor</c> of type <c>T</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor empty (Tensor shape, TF_DataType dtype, bool? init = null, string name = "Empty")
        {
            var dict = new Dictionary<string, object>();
            dict["shape"] = shape;
            dict["dtype"] = dtype;
            if (init.HasValue)
                dict["init"] = init.Value;
            var op = _op_def_lib._apply_op_helper("Empty", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates and returns an empty tensor list.
        /// </summary>
        /// <param name="element_shape">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'EmptyTensorList'.
        /// </param>
        /// <param name="element_dtype">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    All list elements must be tensors of dtype element_dtype and shape compatible
        ///    with element_shape.
        ///    
        ///    handle: an empty tensor list.
        ///    element_dtype: the type of elements in the list.
        ///    element_shape: a shape compatible with that of elements in the list.
        /// </remarks>
        public static Tensor empty_tensor_list (Tensor element_shape, TF_DataType element_dtype, string name = "EmptyTensorList")
        {
            var dict = new Dictionary<string, object>();
            dict["element_shape"] = element_shape;
            dict["element_dtype"] = element_dtype;
            var op = _op_def_lib._apply_op_helper("EmptyTensorList", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Encode strings into web-safe base64 format.
        /// </summary>
        /// <param name="input">
        ///    Strings to be encoded.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'EncodeBase64'.
        /// </param>
        /// <param name="pad">
        ///    Bool whether padding is applied at the ends.
        /// </param>
        /// <returns>
        ///    Input strings encoded in base64.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Refer to the following article for more information on base64 format:
        ///    en.wikipedia.org/wiki/Base64. Base64 strings may have padding with '=' at the
        ///    end so that the encoded has length multiple of 4. See Padding section of the
        ///    link above.
        ///    
        ///    Web-safe means that the encoder uses - and _ instead of + and /.
        /// </remarks>
        public static Tensor encode_base64 (Tensor input, bool? pad = null, string name = "EncodeBase64")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (pad.HasValue)
                dict["pad"] = pad.Value;
            var op = _op_def_lib._apply_op_helper("EncodeBase64", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    JPEG-encode an image.
        /// </summary>
        /// <param name="image">
        ///    3-D with shape <c>[height, width, channels]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'EncodeJpeg'.
        /// </param>
        /// <param name="format">
        ///    Per pixel image format.
        /// </param>
        /// <param name="quality">
        ///    Quality of the compression from 0 to 100 (higher is better and slower).
        /// </param>
        /// <param name="progressive">
        ///    If True, create a JPEG that loads progressively (coarse to fine).
        /// </param>
        /// <param name="optimize_size">
        ///    If True, spend CPU/RAM to reduce size with no quality change.
        /// </param>
        /// <param name="chroma_downsampling">
        ///    See http://en.wikipedia.org/wiki/Chroma_subsampling.
        /// </param>
        /// <param name="density_unit">
        ///    Unit used to specify <c>x_density</c> and <c>y_density</c>:
        ///    pixels per inch (<c>'in'</c>) or centimeter (<c>'cm'</c>).
        /// </param>
        /// <param name="x_density">
        ///    Horizontal pixels per density unit.
        /// </param>
        /// <param name="y_density">
        ///    Vertical pixels per density unit.
        /// </param>
        /// <param name="xmp_metadata">
        ///    If not empty, embed this XMP metadata in the image header.
        /// </param>
        /// <returns>
        ///    0-D. JPEG-encoded image.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    <c>image</c> is a 3-D uint8 Tensor of shape <c>[height, width, channels]</c>.
        ///    
        ///    The attr <c>format</c> can be used to override the color format of the encoded
        ///    output.  Values can be:
        ///    
        ///    *   <c>''</c>: Use a default format based on the number of channels in the image.
        ///    *   <c>grayscale</c>: Output a grayscale JPEG image.  The <c>channels</c> dimension
        ///    of <c>image</c> must be 1.
        ///    *   <c>rgb</c>: Output an RGB JPEG image. The <c>channels</c> dimension
        ///    of <c>image</c> must be 3.
        ///    
        ///    If <c>format</c> is not specified or is the empty string, a default format is picked
        ///    in function of the number of channels in <c>image</c>:
        ///    
        ///    *   1: Output a grayscale image.
        ///    *   3: Output an RGB image.
        /// </remarks>
        public static Tensor encode_jpeg (Tensor image, string format = null, int? quality = null, bool? progressive = null, bool? optimize_size = null, bool? chroma_downsampling = null, string density_unit = null, int? x_density = null, int? y_density = null, string xmp_metadata = null, string name = "EncodeJpeg")
        {
            var dict = new Dictionary<string, object>();
            dict["image"] = image;
            if (format != null)
                dict["format"] = format;
            if (quality.HasValue)
                dict["quality"] = quality.Value;
            if (progressive.HasValue)
                dict["progressive"] = progressive.Value;
            if (optimize_size.HasValue)
                dict["optimize_size"] = optimize_size.Value;
            if (chroma_downsampling.HasValue)
                dict["chroma_downsampling"] = chroma_downsampling.Value;
            if (density_unit != null)
                dict["density_unit"] = density_unit;
            if (x_density.HasValue)
                dict["x_density"] = x_density.Value;
            if (y_density.HasValue)
                dict["y_density"] = y_density.Value;
            if (xmp_metadata != null)
                dict["xmp_metadata"] = xmp_metadata;
            var op = _op_def_lib._apply_op_helper("EncodeJpeg", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    PNG-encode an image.
        /// </summary>
        /// <param name="image">
        ///    3-D with shape <c>[height, width, channels]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'EncodePng'.
        /// </param>
        /// <param name="compression">
        ///    Compression level.
        /// </param>
        /// <returns>
        ///    0-D. PNG-encoded image.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    <c>image</c> is a 3-D uint8 or uint16 Tensor of shape <c>[height, width, channels]</c>
        ///    where <c>channels</c> is:
        ///    
        ///    *   1: for grayscale.
        ///    *   2: for grayscale + alpha.
        ///    *   3: for RGB.
        ///    *   4: for RGBA.
        ///    
        ///    The ZLIB compression level, <c>compression</c>, can be -1 for the PNG-encoder
        ///    default or a value from 0 to 9.  9 is the highest compression level, generating
        ///    the smallest output, but is slower.
        /// </remarks>
        public static Tensor encode_png (Tensor image, int? compression = null, string name = "EncodePng")
        {
            var dict = new Dictionary<string, object>();
            dict["image"] = image;
            if (compression.HasValue)
                dict["compression"] = compression.Value;
            var op = _op_def_lib._apply_op_helper("EncodePng", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    The op serializes protobuf messages provided in the input tensors.
        /// </summary>
        /// <param name="sizes">
        ///    Tensor of int32 with shape <c>[batch_shape, len(field_names)]</c>.
        /// </param>
        /// <param name="values">
        ///    List of tensors containing values for the corresponding field.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'EncodeProto'.
        /// </param>
        /// <param name="field_names">
        ///    Optional argument
        ///    List of strings containing proto field names.
        /// </param>
        /// <param name="message_type">
        ///    Optional argument
        ///    Name of the proto message type to decode.
        /// </param>
        /// <param name="descriptor_source">
        /// </param>
        /// <returns>
        ///    Tensor of serialized protos with shape <c>batch_shape</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The types of the tensors in <c>values</c> must match the schema for the
        ///    fields specified in <c>field_names</c>. All the tensors in <c>values</c> must
        ///    have a common shape prefix, *batch_shape*.
        ///    
        ///    The <c>sizes</c> tensor specifies repeat counts for each field.  The repeat
        ///    count (last dimension) of a each tensor in <c>values</c> must be greater
        ///    than or equal to corresponding repeat count in <c>sizes</c>.
        ///    
        ///    A <c>message_type</c> name must be provided to give context for the field
        ///    names. The actual message descriptor can be looked up either in the
        ///    linked-in descriptor pool or a filename provided by the caller using
        ///    the <c>descriptor_source</c> attribute.
        ///    
        ///    The <c>descriptor_source</c> attribute selects a source of protocol
        ///    descriptors to consult when looking up <c>message_type</c>. This may be a
        ///    filename containing a serialized <c>FileDescriptorSet</c> message,
        ///    or the special value <c>local://</c>, in which case only descriptors linked
        ///    into the code will be searched; the filename can be on any filesystem
        ///    accessible to TensorFlow.
        ///    
        ///    You can build a <c>descriptor_source</c> file using the <c>--descriptor_set_out</c>
        ///    and <c>--include_imports</c> options to the protocol compiler <c>protoc</c>.
        ///    
        ///    The <c>local://</c> database only covers descriptors linked into the
        ///    code via C++ libraries, not Python imports. You can link in a proto descriptor
        ///    by creating a cc_library target with alwayslink=1.
        ///    
        ///    There are a few special cases in the value mapping:
        ///    
        ///    Submessage and group fields must be pre-serialized as TensorFlow strings.
        ///    
        ///    TensorFlow lacks support for unsigned int64s, so they must be
        ///    represented as <c>tf.int64</c> with the same twos-complement bit pattern
        ///    (the obvious way).
        ///    
        ///    Unsigned int32 values can be represented exactly with <c>tf.int64</c>, or
        ///    with sign wrapping if the input is of type <c>tf.int32</c>.
        /// </remarks>
        public static Tensor encode_proto (Tensor sizes, Tensor[] values, string[] field_names, string message_type, string descriptor_source = null, string name = "EncodeProto")
        {
            var dict = new Dictionary<string, object>();
            dict["sizes"] = sizes;
            dict["values"] = values;
            dict["field_names"] = field_names;
            dict["message_type"] = message_type;
            if (descriptor_source != null)
                dict["descriptor_source"] = descriptor_source;
            var op = _op_def_lib._apply_op_helper("EncodeProto", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Encode audio data using the WAV file format.
        /// </summary>
        /// <param name="audio">
        ///    2-D with shape <c>[length, channels]</c>.
        /// </param>
        /// <param name="sample_rate">
        ///    Scalar containing the sample frequency.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'EncodeWav'.
        /// </param>
        /// <returns>
        ///    0-D. WAV-encoded file contents.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation will generate a string suitable to be saved out to create a .wav
        ///    audio file. It will be encoded in the 16-bit PCM format. It takes in float
        ///    values in the range -1.0f to 1.0f, and any outside that value will be clamped to
        ///    that range.
        ///    
        ///    <c>audio</c> is a 2-D float Tensor of shape <c>[length, channels]</c>.
        ///    <c>sample_rate</c> is a scalar Tensor holding the rate to use (e.g. 44100).
        /// </remarks>
        public static Tensor encode_wav (Tensor audio, Tensor sample_rate, string name = "EncodeWav")
        {
            var dict = new Dictionary<string, object>();
            dict["audio"] = audio;
            dict["sample_rate"] = sample_rate;
            var op = _op_def_lib._apply_op_helper("EncodeWav", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Ensures that the tensor's shape matches the expected shape.
        /// </summary>
        /// <param name="input">
        ///    A tensor, whose shape is to be validated.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'EnsureShape'.
        /// </param>
        /// <param name="shape">
        ///    Optional argument
        ///    The expected (possibly partially specified) shape of the input tensor.
        /// </param>
        /// <returns>
        ///    A tensor with the same shape and contents as the input tensor or value.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Raises an error if the input tensor's shape does not match the specified shape.
        ///    Returns the input tensor otherwise.
        /// </remarks>
        public static Tensor ensure_shape (Tensor input, TensorShape shape, string name = "EnsureShape")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["shape"] = shape;
            var op = _op_def_lib._apply_op_helper("EnsureShape", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates or finds a child frame, and makes <c>data</c> available to the child frame.
        /// </summary>
        /// <param name="data">
        ///    The tensor to be made available to the child frame.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Enter'.
        /// </param>
        /// <param name="frame_name">
        ///    Optional argument
        ///    The name of the child frame.
        /// </param>
        /// <param name="is_constant">
        ///    If true, the output is constant within the child frame.
        /// </param>
        /// <param name="parallel_iterations">
        ///    The number of iterations allowed to run in parallel.
        /// </param>
        /// <returns>
        ///    The same tensor as <c>data</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op is used together with <c>Exit</c> to create loops in the graph.
        ///    The unique <c>frame_name</c> is used by the <c>Executor</c> to identify frames. If
        ///    <c>is_constant</c> is true, <c>output</c> is a constant in the child frame; otherwise
        ///    it may be changed in the child frame. At most <c>parallel_iterations</c> iterations
        ///    are run in parallel in the child frame.
        /// </remarks>
        public static Tensor enter (Tensor data, string frame_name, bool? is_constant = null, int? parallel_iterations = null, string name = "Enter")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            dict["frame_name"] = frame_name;
            if (is_constant.HasValue)
                dict["is_constant"] = is_constant.Value;
            if (parallel_iterations.HasValue)
                dict["parallel_iterations"] = parallel_iterations.Value;
            var op = _op_def_lib._apply_op_helper("Enter", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the truth value of (x == y) element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Equal'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    *NOTE*: <c>Equal</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor equal (Tensor x, Tensor y, string name = "Equal")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("Equal", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the Gauss error function of <c>x</c> element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Erf'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor erf (Tensor x, string name = "Erf")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Erf", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the complementary error function of <c>x</c> element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Erfc'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor erfc (Tensor x, string name = "Erfc")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Erfc", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Exits the current frame to its parent frame.
        /// </summary>
        /// <param name="data">
        ///    The tensor to be made available to the parent frame.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Exit'.
        /// </param>
        /// <returns>
        ///    The same tensor as <c>data</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Exit makes its input <c>data</c> available to the parent frame.
        /// </remarks>
        public static Tensor exit (Tensor data, string name = "Exit")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            var op = _op_def_lib._apply_op_helper("Exit", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes exponential of x element-wise.  \\(y = e^x\\).
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Exp'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor exp (Tensor x, string name = "Exp")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Exp", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Inserts a dimension of 1 into a tensor's shape.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="dim">
        ///    0-D (scalar). Specifies the dimension index at which to
        ///    expand the shape of <c>input</c>. Must be in the range
        ///    <c>[-rank(input) - 1, rank(input)]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ExpandDims'.
        /// </param>
        /// <returns>
        ///    Contains the same data as <c>input</c>, but its shape has an additional
        ///    dimension of size 1 added.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given a tensor <c>input</c>, this operation inserts a dimension of 1 at the
        ///    dimension index <c>axis</c> of <c>input</c>'s shape. The dimension index <c>axis</c> starts at
        ///    zero; if you specify a negative number for <c>axis</c> it is counted backward from
        ///    the end.
        ///    
        ///    This operation is useful if you want to add a batch dimension to a single
        ///    element. For example, if you have a single image of shape <c>[height, width,
        ///    channels]</c>, you can make it a batch of 1 image with <c>expand_dims(image, 0)</c>,
        ///    which will make the shape <c>[1, height, width, channels]</c>.
        ///    
        ///    Other examples:
        ///    
        ///   <code>
        ///    # 't' is a tensor of shape [2]
        ///    shape(expand_dims(t, 0)) ==&amp;gt; [1, 2]
        ///    shape(expand_dims(t, 1)) ==&amp;gt; [2, 1]
        ///    shape(expand_dims(t, -1)) ==&amp;gt; [2, 1]
        ///    
        ///    # 't2' is a tensor of shape [2, 3, 5]
        ///    shape(expand_dims(t2, 0)) ==&amp;gt; [1, 2, 3, 5]
        ///    shape(expand_dims(t2, 2)) ==&amp;gt; [2, 3, 1, 5]
        ///    shape(expand_dims(t2, 3)) ==&amp;gt; [2, 3, 5, 1]
        ///   </code>
        ///    
        ///    This operation requires that:
        ///    
        ///    <c>-1-input.dims() &amp;lt;= dim &amp;lt;= input.dims()</c>
        ///    
        ///    This operation is related to <c>squeeze()</c>, which removes dimensions of
        ///    size 1.
        /// </remarks>
        public static Tensor expand_dims (Tensor input, Tensor dim, string name = "ExpandDims")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["dim"] = dim;
            var op = _op_def_lib._apply_op_helper("ExpandDims", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes exponential of x - 1 element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Expm1'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    I.e., \\(y = (\exp x) - 1\\).
        /// </remarks>
        public static Tensor expm1 (Tensor x, string name = "Expm1")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Expm1", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Extracts a glimpse from the input tensor.
        /// </summary>
        /// <param name="input">
        ///    A 4-D float tensor of shape <c>[batch_size, height, width, channels]</c>.
        /// </param>
        /// <param name="size">
        ///    A 1-D tensor of 2 elements containing the size of the glimpses
        ///    to extract.  The glimpse height must be specified first, following
        ///    by the glimpse width.
        /// </param>
        /// <param name="offsets">
        ///    A 2-D integer tensor of shape <c>[batch_size, 2]</c> containing
        ///    the y, x locations of the center of each window.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ExtractGlimpse'.
        /// </param>
        /// <param name="centered">
        ///    indicates if the offset coordinates are centered relative to
        ///    the image, in which case the (0, 0) offset is relative to the center
        ///    of the input images. If false, the (0,0) offset corresponds to the
        ///    upper left corner of the input images.
        /// </param>
        /// <param name="normalized">
        ///    indicates if the offset coordinates are normalized.
        /// </param>
        /// <param name="uniform_noise">
        ///    indicates if the noise should be generated using a
        ///    uniform distribution or a Gaussian distribution.
        /// </param>
        /// <returns>
        ///    A tensor representing the glimpses <c>[batch_size,
        ///    glimpse_height, glimpse_width, channels]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Returns a set of windows called glimpses extracted at location
        ///    <c>offsets</c> from the input tensor. If the windows only partially
        ///    overlaps the inputs, the non overlapping areas will be filled with
        ///    random noise.
        ///    
        ///    The result is a 4-D tensor of shape <c>[batch_size, glimpse_height,
        ///    glimpse_width, channels]</c>. The channels and batch dimensions are the
        ///    same as that of the input tensor. The height and width of the output
        ///    windows are specified in the <c>size</c> parameter.
        ///    
        ///    The argument <c>normalized</c> and <c>centered</c> controls how the windows are built:
        ///    
        ///    * If the coordinates are normalized but not centered, 0.0 and 1.0
        ///    correspond to the minimum and maximum of each height and width
        ///    dimension.
        ///    * If the coordinates are both normalized and centered, they range from
        ///    -1.0 to 1.0. The coordinates (-1.0, -1.0) correspond to the upper
        ///    left corner, the lower right corner is located at (1.0, 1.0) and the
        ///    center is at (0, 0).
        ///    * If the coordinates are not normalized they are interpreted as
        ///    numbers of pixels.
        /// </remarks>
        public static Tensor extract_glimpse (Tensor input, Tensor size, Tensor offsets, bool? centered = null, bool? normalized = null, bool? uniform_noise = null, string name = "ExtractGlimpse")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["size"] = size;
            dict["offsets"] = offsets;
            if (centered.HasValue)
                dict["centered"] = centered.Value;
            if (normalized.HasValue)
                dict["normalized"] = normalized.Value;
            if (uniform_noise.HasValue)
                dict["uniform_noise"] = uniform_noise.Value;
            var op = _op_def_lib._apply_op_helper("ExtractGlimpse", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Extract <c>patches</c> from <c>images</c> and put them in the "depth" output dimension.
        /// </summary>
        /// <param name="images">
        ///    4-D Tensor with shape <c>[batch, in_rows, in_cols, depth]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ExtractImagePatches'.
        /// </param>
        /// <param name="ksizes">
        ///    Optional argument
        ///    The size of the sliding window for each dimension of <c>images</c>.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    1-D of length 4. How far the centers of two consecutive patches are in
        ///    the images. Must be: <c>[1, stride_rows, stride_cols, 1]</c>.
        /// </param>
        /// <param name="rates">
        ///    Optional argument
        ///    1-D of length 4. Must be: <c>[1, rate_rows, rate_cols, 1]</c>. This is the
        ///    input stride, specifying how far two consecutive patch samples are in the
        ///    input. Equivalent to extracting patches with
        ///    <c>patch_sizes_eff = patch_sizes + (patch_sizes - 1) * (rates - 1)</c>, followed by
        ///    subsampling them spatially by a factor of <c>rates</c>. This is equivalent to
        ///    <c>rate</c> in dilated (a.k.a. Atrous) convolutions.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        ///    
        ///    We specify the size-related attributes as:
        ///    
        ///   <code>
        ///    ksizes = [1, ksize_rows, ksize_cols, 1]
        ///    strides = [1, strides_rows, strides_cols, 1]
        ///    rates = [1, rates_rows, rates_cols, 1]
        ///   </code>
        /// </param>
        /// <returns>
        ///    4-D Tensor with shape <c>[batch, out_rows, out_cols, ksize_rows *
        ///    ksize_cols * depth]</c> containing image patches with size
        ///    <c>ksize_rows x ksize_cols x depth</c> vectorized in the "depth" dimension. Note
        ///    <c>out_rows</c> and <c>out_cols</c> are the dimensions of the output patches.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor extract_image_patches (Tensor images, int[] ksizes, int[] strides, int[] rates, string padding, string name = "ExtractImagePatches")
        {
            var dict = new Dictionary<string, object>();
            dict["images"] = images;
            dict["ksizes"] = ksizes;
            dict["strides"] = strides;
            dict["rates"] = rates;
            dict["padding"] = padding;
            var op = _op_def_lib._apply_op_helper("ExtractImagePatches", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Extract the shape information of a JPEG-encoded image.
        /// </summary>
        /// <param name="contents">
        ///    0-D. The JPEG-encoded image.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ExtractJpegShape'.
        /// </param>
        /// <param name="output_type">
        ///    (Optional) The output type of the operation (int32 or int64).
        ///    Defaults to int32.
        /// </param>
        /// <returns>
        ///    1-D. The image shape with format [height, width, channels].
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op only parses the image header, so it is much faster than DecodeJpeg.
        /// </remarks>
        public static Tensor extract_jpeg_shape (Tensor contents, TF_DataType? output_type = null, string name = "ExtractJpegShape")
        {
            var dict = new Dictionary<string, object>();
            dict["contents"] = contents;
            if (output_type.HasValue)
                dict["output_type"] = output_type.Value;
            var op = _op_def_lib._apply_op_helper("ExtractJpegShape", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Fast Fourier transform.
        /// </summary>
        /// <param name="input">
        ///    A complex64 tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FFT'.
        /// </param>
        /// <returns>
        ///    A complex64 tensor of the same shape as <c>input</c>. The inner-most
        ///    dimension of <c>input</c> is replaced with its 1D Fourier transform.
        ///    
        ///    @compatibility(numpy)
        ///    Equivalent to np.fft.fft
        ///    @end_compatibility
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Computes the 1-dimensional discrete Fourier transform over the inner-most
        ///    dimension of <c>input</c>.
        /// </remarks>
        public static Tensor f_f_t (Tensor input, string name = "FFT")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("FFT", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    2D fast Fourier transform.
        /// </summary>
        /// <param name="input">
        ///    A complex64 tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FFT2D'.
        /// </param>
        /// <returns>
        ///    A complex64 tensor of the same shape as <c>input</c>. The inner-most 2
        ///    dimensions of <c>input</c> are replaced with their 2D Fourier transform.
        ///    
        ///    @compatibility(numpy)
        ///    Equivalent to np.fft.fft2
        ///    @end_compatibility
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Computes the 2-dimensional discrete Fourier transform over the inner-most
        ///    2 dimensions of <c>input</c>.
        /// </remarks>
        public static Tensor f_f_t2d (Tensor input, string name = "FFT2D")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("FFT2D", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    3D fast Fourier transform.
        /// </summary>
        /// <param name="input">
        ///    A complex64 tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FFT3D'.
        /// </param>
        /// <returns>
        ///    A complex64 tensor of the same shape as <c>input</c>. The inner-most 3
        ///    dimensions of <c>input</c> are replaced with their 3D Fourier transform.
        ///    
        ///    @compatibility(numpy)
        ///    Equivalent to np.fft.fftn with 3 dimensions.
        ///    @end_compatibility
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Computes the 3-dimensional discrete Fourier transform over the inner-most 3
        ///    dimensions of <c>input</c>.
        /// </remarks>
        public static Tensor f_f_t3d (Tensor input, string name = "FFT3D")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("FFT3D", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A queue that produces elements in first-in first-out order.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FIFOQueue'.
        /// </param>
        /// <param name="component_types">
        ///    Optional argument
        ///    The type of each component in a value.
        /// </param>
        /// <param name="shapes">
        ///    The shape of each component in a value. The length of this attr must
        ///    be either 0 or the same as the length of component_types. If the length of
        ///    this attr is 0, the shapes of queue elements are not constrained, and
        ///    only one element may be dequeued at a time.
        /// </param>
        /// <param name="capacity">
        ///    The upper bound on the number of elements in this queue.
        ///    Negative numbers mean no limit.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this queue is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this queue will be shared under the given name
        ///    across multiple sessions.
        /// </param>
        /// <returns>
        ///    The handle to the queue.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor f_i_f_o_queue (TF_DataType[] component_types, TensorShape[] shapes = null, int? capacity = null, string container = null, string shared_name = null, string name = "FIFOQueue")
        {
            var dict = new Dictionary<string, object>();
            dict["component_types"] = component_types;
            if (shapes != null)
                dict["shapes"] = shapes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("FIFOQueue", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A queue that produces elements in first-in first-out order.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FIFOQueueV2'.
        /// </param>
        /// <param name="component_types">
        ///    Optional argument
        ///    The type of each component in a value.
        /// </param>
        /// <param name="shapes">
        ///    The shape of each component in a value. The length of this attr must
        ///    be either 0 or the same as the length of component_types. If the length of
        ///    this attr is 0, the shapes of queue elements are not constrained, and
        ///    only one element may be dequeued at a time.
        /// </param>
        /// <param name="capacity">
        ///    The upper bound on the number of elements in this queue.
        ///    Negative numbers mean no limit.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this queue is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this queue will be shared under the given name
        ///    across multiple sessions.
        /// </param>
        /// <returns>
        ///    The handle to the queue.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor f_i_f_o_queue_v2 (TF_DataType[] component_types, TensorShape[] shapes = null, int? capacity = null, string container = null, string shared_name = null, string name = "FIFOQueueV2")
        {
            var dict = new Dictionary<string, object>();
            dict["component_types"] = component_types;
            if (shapes != null)
                dict["shapes"] = shapes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("FIFOQueueV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    This op is used as a placeholder in If branch functions. It doesn't provide a
        ///    valid output when run, so must either be removed (e.g. replaced with a
        ///    function input) or guaranteed not to be used (e.g. if mirroring an
        ///    intermediate output needed for the gradient computation of the other branch).
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FakeParam'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The type of the output.
        /// </param>
        /// <param name="shape">
        ///    Optional argument
        ///    The purported shape of the output. This is only used for shape inference;
        ///    the output will not necessarily have this shape. Can be a partial shape.
        /// </param>
        /// <returns>
        ///    \"Fake\" output value. This should not be consumed by another op.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor fake_param (TF_DataType dtype, TensorShape shape, string name = "FakeParam")
        {
            var dict = new Dictionary<string, object>();
            dict["dtype"] = dtype;
            dict["shape"] = shape;
            var op = _op_def_lib._apply_op_helper("FakeParam", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Fake-quantize the 'inputs' tensor, type float to 'outputs' tensor of same type.
        /// </summary>
        /// <param name="inputs">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FakeQuantWithMinMaxArgs'.
        /// </param>
        /// <param name="min">
        /// </param>
        /// <param name="max">
        /// </param>
        /// <param name="num_bits">
        /// </param>
        /// <param name="narrow_range">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Attributes <c>[min; max]</c> define the clamping range for the <c>inputs</c> data.
        ///    <c>inputs</c> values are quantized into the quantization range (<c>[0; 2^num_bits - 1]</c>
        ///    when <c>narrow_range</c> is false and <c>[1; 2^num_bits - 1]</c> when it is true) and
        ///    then de-quantized and output as floats in <c>[min; max]</c> interval.
        ///    <c>num_bits</c> is the bitwidth of the quantization; between 2 and 16, inclusive.
        ///    
        ///    Quantization is called fake since the output is still in floating point.
        /// </remarks>
        public static Tensor fake_quant_with_min_max_args (Tensor inputs, float? min = null, float? max = null, int? num_bits = null, bool? narrow_range = null, string name = "FakeQuantWithMinMaxArgs")
        {
            var dict = new Dictionary<string, object>();
            dict["inputs"] = inputs;
            if (min.HasValue)
                dict["min"] = min.Value;
            if (max.HasValue)
                dict["max"] = max.Value;
            if (num_bits.HasValue)
                dict["num_bits"] = num_bits.Value;
            if (narrow_range.HasValue)
                dict["narrow_range"] = narrow_range.Value;
            var op = _op_def_lib._apply_op_helper("FakeQuantWithMinMaxArgs", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Compute gradients for a FakeQuantWithMinMaxArgs operation.
        /// </summary>
        /// <param name="gradients">
        ///    Backpropagated gradients above the FakeQuantWithMinMaxArgs operation.
        /// </param>
        /// <param name="inputs">
        ///    Values passed as inputs to the FakeQuantWithMinMaxArgs operation.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FakeQuantWithMinMaxArgsGradient'.
        /// </param>
        /// <param name="min">
        /// </param>
        /// <param name="max">
        /// </param>
        /// <param name="num_bits">
        /// </param>
        /// <param name="narrow_range">
        /// </param>
        /// <returns>
        ///    Backpropagated gradients below the FakeQuantWithMinMaxArgs operation:
        ///    <c>gradients * (inputs &amp;gt;= min &amp;&amp; inputs &amp;lt;= max)</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor fake_quant_with_min_max_args_gradient (Tensor gradients, Tensor inputs, float? min = null, float? max = null, int? num_bits = null, bool? narrow_range = null, string name = "FakeQuantWithMinMaxArgsGradient")
        {
            var dict = new Dictionary<string, object>();
            dict["gradients"] = gradients;
            dict["inputs"] = inputs;
            if (min.HasValue)
                dict["min"] = min.Value;
            if (max.HasValue)
                dict["max"] = max.Value;
            if (num_bits.HasValue)
                dict["num_bits"] = num_bits.Value;
            if (narrow_range.HasValue)
                dict["narrow_range"] = narrow_range.Value;
            var op = _op_def_lib._apply_op_helper("FakeQuantWithMinMaxArgsGradient", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Fake-quantize the 'inputs' tensor of type float via global float scalars <c>min</c>
        /// </summary>
        /// <param name="inputs">
        /// </param>
        /// <param name="min">
        /// </param>
        /// <param name="max">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FakeQuantWithMinMaxVars'.
        /// </param>
        /// <param name="num_bits">
        /// </param>
        /// <param name="narrow_range">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    and <c>max</c> to 'outputs' tensor of same shape as <c>inputs</c>.
        ///    
        ///    <c>[min; max]</c> define the clamping range for the <c>inputs</c> data.
        ///    <c>inputs</c> values are quantized into the quantization range (<c>[0; 2^num_bits - 1]</c>
        ///    when <c>narrow_range</c> is false and <c>[1; 2^num_bits - 1]</c> when it is true) and
        ///    then de-quantized and output as floats in <c>[min; max]</c> interval.
        ///    <c>num_bits</c> is the bitwidth of the quantization; between 2 and 16, inclusive.
        ///    
        ///    This operation has a gradient and thus allows for training <c>min</c> and <c>max</c>
        ///    values.
        /// </remarks>
        public static Tensor fake_quant_with_min_max_vars (Tensor inputs, Tensor min, Tensor max, int? num_bits = null, bool? narrow_range = null, string name = "FakeQuantWithMinMaxVars")
        {
            var dict = new Dictionary<string, object>();
            dict["inputs"] = inputs;
            dict["min"] = min;
            dict["max"] = max;
            if (num_bits.HasValue)
                dict["num_bits"] = num_bits.Value;
            if (narrow_range.HasValue)
                dict["narrow_range"] = narrow_range.Value;
            var op = _op_def_lib._apply_op_helper("FakeQuantWithMinMaxVars", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Compute gradients for a FakeQuantWithMinMaxVars operation.
        /// </summary>
        /// <param name="gradients">
        ///    Backpropagated gradients above the FakeQuantWithMinMaxVars operation.
        /// </param>
        /// <param name="inputs">
        ///    Values passed as inputs to the FakeQuantWithMinMaxVars operation.
        ///    min, max: Quantization interval, scalar floats.
        /// </param>
        /// <param name="min">
        /// </param>
        /// <param name="max">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FakeQuantWithMinMaxVarsGradient'.
        /// </param>
        /// <param name="num_bits">
        ///    The bitwidth of the quantization; between 2 and 8, inclusive.
        /// </param>
        /// <param name="narrow_range">
        ///    Whether to quantize into 2^num_bits - 1 distinct values.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    backprops_wrt_input : Backpropagated gradients w.r.t. inputs:
        ///    <c>gradients * (inputs &amp;gt;= min &amp;&amp; inputs &amp;lt;= max)</c>.
        ///    backprop_wrt_min : Backpropagated gradients w.r.t. min parameter:
        ///    <c>sum(gradients * (inputs &amp;lt; min))</c>.
        ///    backprop_wrt_max : Backpropagated gradients w.r.t. max parameter:
        ///    <c>sum(gradients * (inputs &amp;gt; max))</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor backprops_wrt_input, Tensor backprop_wrt_min, Tensor backprop_wrt_max) fake_quant_with_min_max_vars_gradient (Tensor gradients, Tensor inputs, Tensor min, Tensor max, int? num_bits = null, bool? narrow_range = null, string name = "FakeQuantWithMinMaxVarsGradient")
        {
            var dict = new Dictionary<string, object>();
            dict["gradients"] = gradients;
            dict["inputs"] = inputs;
            dict["min"] = min;
            dict["max"] = max;
            if (num_bits.HasValue)
                dict["num_bits"] = num_bits.Value;
            if (narrow_range.HasValue)
                dict["narrow_range"] = narrow_range.Value;
            var op = _op_def_lib._apply_op_helper("FakeQuantWithMinMaxVarsGradient", name: name, keywords: dict);
            int _idx = 0;
            var backprops_wrt_input = op.outputs[_idx++];
            var backprop_wrt_min = op.outputs[_idx++];
            var backprop_wrt_max = op.outputs[_idx++];
            return (backprops_wrt_input, backprop_wrt_min, backprop_wrt_max);
        }

        /// <summary>
        ///    Fake-quantize the 'inputs' tensor of type float and one of the shapes: <c>[d]</c>,
        /// </summary>
        /// <param name="inputs">
        /// </param>
        /// <param name="min">
        /// </param>
        /// <param name="max">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FakeQuantWithMinMaxVarsPerChannel'.
        /// </param>
        /// <param name="num_bits">
        /// </param>
        /// <param name="narrow_range">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    <c>[b, d]</c> <c>[b, h, w, d]</c> via per-channel floats <c>min</c> and <c>max</c> of shape <c>[d]</c>
        ///    to 'outputs' tensor of same shape as <c>inputs</c>.
        ///    
        ///    <c>[min; max]</c> define the clamping range for the <c>inputs</c> data.
        ///    <c>inputs</c> values are quantized into the quantization range (<c>[0; 2^num_bits - 1]</c>
        ///    when <c>narrow_range</c> is false and <c>[1; 2^num_bits - 1]</c> when it is true) and
        ///    then de-quantized and output as floats in <c>[min; max]</c> interval.
        ///    <c>num_bits</c> is the bitwidth of the quantization; between 2 and 16, inclusive.
        ///    
        ///    This operation has a gradient and thus allows for training <c>min</c> and <c>max</c>
        ///    values.
        /// </remarks>
        public static Tensor fake_quant_with_min_max_vars_per_channel (Tensor inputs, Tensor min, Tensor max, int? num_bits = null, bool? narrow_range = null, string name = "FakeQuantWithMinMaxVarsPerChannel")
        {
            var dict = new Dictionary<string, object>();
            dict["inputs"] = inputs;
            dict["min"] = min;
            dict["max"] = max;
            if (num_bits.HasValue)
                dict["num_bits"] = num_bits.Value;
            if (narrow_range.HasValue)
                dict["narrow_range"] = narrow_range.Value;
            var op = _op_def_lib._apply_op_helper("FakeQuantWithMinMaxVarsPerChannel", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Compute gradients for a FakeQuantWithMinMaxVarsPerChannel operation.
        /// </summary>
        /// <param name="gradients">
        ///    Backpropagated gradients above the FakeQuantWithMinMaxVars operation,
        ///    shape one of: <c>[d]</c>, <c>[b, d]</c>,  <c>[b, h, w, d]</c>.
        /// </param>
        /// <param name="inputs">
        ///    Values passed as inputs to the FakeQuantWithMinMaxVars operation, shape
        ///    same as <c>gradients</c>.
        ///    min, max: Quantization interval, floats of shape <c>[d]</c>.
        /// </param>
        /// <param name="min">
        /// </param>
        /// <param name="max">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FakeQuantWithMinMaxVarsPerChannelGradient'.
        /// </param>
        /// <param name="num_bits">
        ///    The bitwidth of the quantization; between 2 and 16, inclusive.
        /// </param>
        /// <param name="narrow_range">
        ///    Whether to quantize into 2^num_bits - 1 distinct values.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    backprops_wrt_input : Backpropagated gradients w.r.t. inputs, shape same as
        ///    <c>inputs</c>:
        ///    <c>gradients * (inputs &amp;gt;= min &amp;&amp; inputs &amp;lt;= max)</c>.
        ///    backprop_wrt_min : Backpropagated gradients w.r.t. min parameter, shape <c>[d]</c>:
        ///    <c>sum_per_d(gradients * (inputs &amp;lt; min))</c>.
        ///    backprop_wrt_max : Backpropagated gradients w.r.t. max parameter, shape <c>[d]</c>:
        ///    <c>sum_per_d(gradients * (inputs &amp;gt; max))</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor backprops_wrt_input, Tensor backprop_wrt_min, Tensor backprop_wrt_max) fake_quant_with_min_max_vars_per_channel_gradient (Tensor gradients, Tensor inputs, Tensor min, Tensor max, int? num_bits = null, bool? narrow_range = null, string name = "FakeQuantWithMinMaxVarsPerChannelGradient")
        {
            var dict = new Dictionary<string, object>();
            dict["gradients"] = gradients;
            dict["inputs"] = inputs;
            dict["min"] = min;
            dict["max"] = max;
            if (num_bits.HasValue)
                dict["num_bits"] = num_bits.Value;
            if (narrow_range.HasValue)
                dict["narrow_range"] = narrow_range.Value;
            var op = _op_def_lib._apply_op_helper("FakeQuantWithMinMaxVarsPerChannelGradient", name: name, keywords: dict);
            int _idx = 0;
            var backprops_wrt_input = op.outputs[_idx++];
            var backprop_wrt_min = op.outputs[_idx++];
            var backprop_wrt_max = op.outputs[_idx++];
            return (backprops_wrt_input, backprop_wrt_min, backprop_wrt_max);
        }

        /// <summary>
        ///    Deprecated. Do not use.
        /// </summary>
        /// <param name="resource">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FakeQueue'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor fake_queue (Tensor resource, string name = "FakeQueue")
        {
            var dict = new Dictionary<string, object>();
            dict["resource"] = resource;
            var op = _op_def_lib._apply_op_helper("FakeQueue", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a tensor filled with a scalar value.
        /// </summary>
        /// <param name="dims">
        ///    1-D. Represents the shape of the output tensor.
        /// </param>
        /// <param name="value">
        ///    0-D (scalar). Value to fill the returned tensor.
        ///    
        ///    @compatibility(numpy)
        ///    Equivalent to np.full
        ///    @end_compatibility
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Fill'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation creates a tensor of shape <c>dims</c> and fills it with <c>value</c>.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # Output tensor has shape [2, 3].
        ///    fill([2, 3], 9) ==&amp;gt; [[9, 9, 9]
        ///    [9, 9, 9]]
        ///   </code>
        ///    
        ///    <c>tf.fill</c> differs from <c>tf.constant</c> in a few ways:
        ///    
        ///    *   <c>tf.fill</c> only supports scalar contents, whereas <c>tf.constant</c> supports
        ///    Tensor values.
        ///    *   <c>tf.fill</c> creates an Op in the computation graph that constructs the actual
        ///    Tensor value at runtime. This is in contrast to <c>tf.constant</c> which embeds
        ///    the entire Tensor into the graph with a <c>Const</c> node.
        ///    *   Because <c>tf.fill</c> evaluates at graph runtime, it supports dynamic shapes
        ///    based on other runtime Tensors, unlike <c>tf.constant</c>.
        /// </remarks>
        public static Tensor fill (Tensor dims, Tensor value, string name = "Fill")
        {
            var dict = new Dictionary<string, object>();
            dict["dims"] = dims;
            dict["value"] = value;
            var op = _op_def_lib._apply_op_helper("Fill", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a dataset containing elements of first component of <c>input_dataset</c> having true in the last component.
        /// </summary>
        /// <param name="input_dataset">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FilterByLastComponentDataset'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor filter_by_last_component_dataset (Tensor input_dataset, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "FilterByLastComponentDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("FilterByLastComponentDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a dataset that emits the records from one or more binary files.
        /// </summary>
        /// <param name="filenames">
        ///    A scalar or a vector containing the name(s) of the file(s) to be
        ///    read.
        /// </param>
        /// <param name="header_bytes">
        ///    A scalar representing the number of bytes to skip at the
        ///    beginning of a file.
        /// </param>
        /// <param name="record_bytes">
        ///    A scalar representing the number of bytes in each record.
        /// </param>
        /// <param name="footer_bytes">
        ///    A scalar representing the number of bytes to skip at the end
        ///    of a file.
        /// </param>
        /// <param name="buffer_size">
        ///    A scalar representing the number of bytes to buffer. Must be &amp;gt; 0.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FixedLengthRecordDataset'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor fixed_length_record_dataset (Tensor filenames, Tensor header_bytes, Tensor record_bytes, Tensor footer_bytes, Tensor buffer_size, string name = "FixedLengthRecordDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["filenames"] = filenames;
            dict["header_bytes"] = header_bytes;
            dict["record_bytes"] = record_bytes;
            dict["footer_bytes"] = footer_bytes;
            dict["buffer_size"] = buffer_size;
            var op = _op_def_lib._apply_op_helper("FixedLengthRecordDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A Reader that outputs fixed-length records from a file.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FixedLengthRecordReader'.
        /// </param>
        /// <param name="record_bytes">
        ///    Optional argument
        ///    Number of bytes in the record.
        /// </param>
        /// <param name="header_bytes">
        ///    Number of bytes in the header, defaults to 0.
        /// </param>
        /// <param name="footer_bytes">
        ///    Number of bytes in the footer, defaults to 0.
        /// </param>
        /// <param name="hop_bytes">
        ///    Number of bytes to hop before each read. Default of 0 means using
        ///    record_bytes.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this reader is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this reader is named in the given bucket
        ///    with this shared_name. Otherwise, the node name is used instead.
        /// </param>
        /// <returns>
        ///    The handle to reference the Reader.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor fixed_length_record_reader (int record_bytes, int? header_bytes = null, int? footer_bytes = null, int? hop_bytes = null, string container = null, string shared_name = null, string name = "FixedLengthRecordReader")
        {
            var dict = new Dictionary<string, object>();
            dict["record_bytes"] = record_bytes;
            if (header_bytes.HasValue)
                dict["header_bytes"] = header_bytes.Value;
            if (footer_bytes.HasValue)
                dict["footer_bytes"] = footer_bytes.Value;
            if (hop_bytes.HasValue)
                dict["hop_bytes"] = hop_bytes.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("FixedLengthRecordReader", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A Reader that outputs fixed-length records from a file.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FixedLengthRecordReaderV2'.
        /// </param>
        /// <param name="record_bytes">
        ///    Optional argument
        ///    Number of bytes in the record.
        /// </param>
        /// <param name="header_bytes">
        ///    Number of bytes in the header, defaults to 0.
        /// </param>
        /// <param name="footer_bytes">
        ///    Number of bytes in the footer, defaults to 0.
        /// </param>
        /// <param name="hop_bytes">
        ///    Number of bytes to hop before each read. Default of 0 means using
        ///    record_bytes.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this reader is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this reader is named in the given bucket
        ///    with this shared_name. Otherwise, the node name is used instead.
        /// </param>
        /// <param name="encoding">
        ///    The type of encoding for the file. Currently ZLIB and GZIP
        ///    are supported. Defaults to none.
        /// </param>
        /// <returns>
        ///    The handle to reference the Reader.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor fixed_length_record_reader_v2 (int record_bytes, int? header_bytes = null, int? footer_bytes = null, int? hop_bytes = null, string container = null, string shared_name = null, string encoding = null, string name = "FixedLengthRecordReaderV2")
        {
            var dict = new Dictionary<string, object>();
            dict["record_bytes"] = record_bytes;
            if (header_bytes.HasValue)
                dict["header_bytes"] = header_bytes.Value;
            if (footer_bytes.HasValue)
                dict["footer_bytes"] = footer_bytes.Value;
            if (hop_bytes.HasValue)
                dict["hop_bytes"] = hop_bytes.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            if (encoding != null)
                dict["encoding"] = encoding;
            var op = _op_def_lib._apply_op_helper("FixedLengthRecordReaderV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Generates labels for candidate sampling with a learned unigram distribution.
        /// </summary>
        /// <param name="true_classes">
        ///    A batch_size * num_true matrix, in which each row contains the
        ///    IDs of the num_true target_classes in the corresponding original label.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FixedUnigramCandidateSampler'.
        /// </param>
        /// <param name="num_true">
        ///    Optional argument
        ///    Number of true labels per context.
        /// </param>
        /// <param name="num_sampled">
        ///    Optional argument
        ///    Number of candidates to randomly sample.
        /// </param>
        /// <param name="unique">
        ///    Optional argument
        ///    If unique is true, we sample with rejection, so that all sampled
        ///    candidates in a batch are unique. This requires some approximation to
        ///    estimate the post-rejection sampling probabilities.
        /// </param>
        /// <param name="range_max">
        ///    Optional argument
        ///    The sampler will sample integers from the interval [0, range_max).
        /// </param>
        /// <param name="vocab_file">
        ///    Each valid line in this file (which should have a CSV-like format)
        ///    corresponds to a valid word ID. IDs are in sequential order, starting from
        ///    num_reserved_ids. The last entry in each line is expected to be a value
        ///    corresponding to the count or relative probability. Exactly one of vocab_file
        ///    and unigrams needs to be passed to this op.
        /// </param>
        /// <param name="distortion">
        ///    The distortion is used to skew the unigram probability distribution.
        ///    Each weight is first raised to the distortion's power before adding to the
        ///    internal unigram distribution. As a result, distortion = 1.0 gives regular
        ///    unigram sampling (as defined by the vocab file), and distortion = 0.0 gives
        ///    a uniform distribution.
        /// </param>
        /// <param name="num_reserved_ids">
        ///    Optionally some reserved IDs can be added in the range [0,
        ///    ..., num_reserved_ids) by the users. One use case is that a special unknown
        ///    word token is used as ID 0. These IDs will have a sampling probability of 0.
        /// </param>
        /// <param name="num_shards">
        ///    A sampler can be used to sample from a subset of the original range
        ///    in order to speed up the whole computation through parallelism. This parameter
        ///    (together with 'shard') indicates the number of partitions that are being
        ///    used in the overall computation.
        /// </param>
        /// <param name="shard">
        ///    A sampler can be used to sample from a subset of the original range
        ///    in order to speed up the whole computation through parallelism. This parameter
        ///    (together with 'num_shards') indicates the particular partition number of a
        ///    sampler op, when partitioning is being used.
        /// </param>
        /// <param name="unigrams">
        ///    A list of unigram counts or probabilities, one per ID in sequential
        ///    order. Exactly one of vocab_file and unigrams should be passed to this op.
        /// </param>
        /// <param name="seed">
        ///    If either seed or seed2 are set to be non-zero, the random number
        ///    generator is seeded by the given seed.  Otherwise, it is seeded by a
        ///    random seed.
        /// </param>
        /// <param name="seed2">
        ///    An second seed to avoid seed collision.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    sampled_candidates : A vector of length num_sampled, in which each element is
        ///    the ID of a sampled candidate.
        ///    true_expected_count : A batch_size * num_true matrix, representing
        ///    the number of times each candidate is expected to occur in a batch
        ///    of sampled candidates. If unique=true, then this is a probability.
        ///    sampled_expected_count : A vector of length num_sampled, for each sampled
        ///    candidate representing the number of times the candidate is expected
        ///    to occur in a batch of sampled candidates.  If unique=true, then this is a
        ///    probability.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    A unigram sampler could use a fixed unigram distribution read from a
        ///    file or passed in as an in-memory array instead of building up the distribution
        ///    from data on the fly. There is also an option to skew the distribution by
        ///    applying a distortion power to the weights.
        ///    
        ///    The vocabulary file should be in CSV-like format, with the last field
        ///    being the weight associated with the word.
        ///    
        ///    For each batch, this op picks a single set of sampled candidate labels.
        ///    
        ///    The advantages of sampling candidates per-batch are simplicity and the
        ///    possibility of efficient dense matrix multiplication. The disadvantage is that
        ///    the sampled candidates must be chosen independently of the context and of the
        ///    true labels.
        /// </remarks>
        public static (Tensor sampled_candidates, Tensor true_expected_count, Tensor sampled_expected_count) fixed_unigram_candidate_sampler (Tensor true_classes, int num_true, int num_sampled, bool unique, int range_max, string vocab_file = null, float? distortion = null, int? num_reserved_ids = null, int? num_shards = null, int? shard = null, float[] unigrams = null, int? seed = null, int? seed2 = null, string name = "FixedUnigramCandidateSampler")
        {
            var dict = new Dictionary<string, object>();
            dict["true_classes"] = true_classes;
            dict["num_true"] = num_true;
            dict["num_sampled"] = num_sampled;
            dict["unique"] = unique;
            dict["range_max"] = range_max;
            if (vocab_file != null)
                dict["vocab_file"] = vocab_file;
            if (distortion.HasValue)
                dict["distortion"] = distortion.Value;
            if (num_reserved_ids.HasValue)
                dict["num_reserved_ids"] = num_reserved_ids.Value;
            if (num_shards.HasValue)
                dict["num_shards"] = num_shards.Value;
            if (shard.HasValue)
                dict["shard"] = shard.Value;
            if (unigrams != null)
                dict["unigrams"] = unigrams;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("FixedUnigramCandidateSampler", name: name, keywords: dict);
            int _idx = 0;
            var sampled_candidates = op.outputs[_idx++];
            var true_expected_count = op.outputs[_idx++];
            var sampled_expected_count = op.outputs[_idx++];
            return (sampled_candidates, true_expected_count, sampled_expected_count);
        }

        /// <summary>
        ///    Returns element-wise largest integer not greater than x.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Floor'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor floor (Tensor x, string name = "Floor")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Floor", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns x // y element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FloorDiv'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    *NOTE*: <c>FloorDiv</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor floor_div (Tensor x, Tensor y, string name = "FloorDiv")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("FloorDiv", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns element-wise remainder of division. When <c>x &amp;lt; 0</c> xor <c>y &amp;lt; 0</c> is
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FloorMod'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    true, this follows Python semantics in that the result here is consistent
        ///    with a flooring divide. E.g. <c>floor(x / y) * y + mod(x, y) = x</c>.
        ///    
        ///    *NOTE*: <c>FloorMod</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor floor_mod (Tensor x, Tensor y, string name = "FloorMod")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("FloorMod", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Performs fractional average pooling on the input.
        /// </summary>
        /// <param name="value">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FractionalAvgPool'.
        /// </param>
        /// <param name="pooling_ratio">
        ///    Optional argument
        ///    Pooling ratio for each dimension of <c>value</c>, currently only
        ///    supports row and col dimension and should be &amp;gt;= 1.0. For example, a valid
        ///    pooling ratio looks like [1.0, 1.44, 1.73, 1.0]. The first and last elements
        ///    must be 1.0 because we don't allow pooling on batch and channels
        ///    dimensions. 1.44 and 1.73 are pooling ratio on height and width dimensions
        ///    respectively.
        /// </param>
        /// <param name="pseudo_random">
        ///    When set to True, generates the pooling sequence in a
        ///    pseudorandom fashion, otherwise, in a random fashion. Check paper [Benjamin
        ///    Graham, Fractional Max-Pooling](http://arxiv.org/abs/1412.6071) for
        ///    difference between pseudorandom and random.
        /// </param>
        /// <param name="overlapping">
        ///    When set to True, it means when pooling, the values at the boundary
        ///    of adjacent pooling cells are used by both cells. For example:
        ///    
        ///    <c>index  0  1  2  3  4</c>
        ///    
        ///    <c>value  20 5  16 3  7</c>
        ///    
        ///    If the pooling sequence is [0, 2, 4], then 16, at index 2 will be used twice.
        ///    The result would be [41/3, 26/3] for fractional avg pooling.
        /// </param>
        /// <param name="deterministic">
        ///    When set to True, a fixed pooling region will be used when
        ///    iterating over a FractionalAvgPool node in the computation graph. Mainly used
        ///    in unit test to make FractionalAvgPool deterministic.
        /// </param>
        /// <param name="seed">
        ///    If either seed or seed2 are set to be non-zero, the random number
        ///    generator is seeded by the given seed.  Otherwise, it is seeded by a
        ///    random seed.
        /// </param>
        /// <param name="seed2">
        ///    An second seed to avoid seed collision.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output : output tensor after fractional avg pooling.
        ///    row_pooling_sequence : row pooling sequence, needed to calculate gradient.
        ///    col_pooling_sequence : column pooling sequence, needed to calculate gradient.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Fractional average pooling is similar to Fractional max pooling in the pooling
        ///    region generation step. The only difference is that after pooling regions are
        ///    generated, a mean operation is performed instead of a max operation in each
        ///    pooling region.
        /// </remarks>
        public static (Tensor output, Tensor row_pooling_sequence, Tensor col_pooling_sequence) fractional_avg_pool (Tensor value, float[] pooling_ratio, bool? pseudo_random = null, bool? overlapping = null, bool? deterministic = null, int? seed = null, int? seed2 = null, string name = "FractionalAvgPool")
        {
            var dict = new Dictionary<string, object>();
            dict["value"] = value;
            dict["pooling_ratio"] = pooling_ratio;
            if (pseudo_random.HasValue)
                dict["pseudo_random"] = pseudo_random.Value;
            if (overlapping.HasValue)
                dict["overlapping"] = overlapping.Value;
            if (deterministic.HasValue)
                dict["deterministic"] = deterministic.Value;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("FractionalAvgPool", name: name, keywords: dict);
            int _idx = 0;
            var output = op.outputs[_idx++];
            var row_pooling_sequence = op.outputs[_idx++];
            var col_pooling_sequence = op.outputs[_idx++];
            return (output, row_pooling_sequence, col_pooling_sequence);
        }

        /// <summary>
        ///    Computes gradient of the FractionalAvgPool function.
        /// </summary>
        /// <param name="orig_input_tensor_shape">
        ///    Original input tensor shape for <c>fractional_avg_pool</c>
        /// </param>
        /// <param name="out_backprop">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.  Gradients
        ///    w.r.t. the output of <c>fractional_avg_pool</c>.
        /// </param>
        /// <param name="row_pooling_sequence">
        ///    row pooling sequence, form pooling region with
        ///    col_pooling_sequence.
        /// </param>
        /// <param name="col_pooling_sequence">
        ///    column pooling sequence, form pooling region with
        ///    row_pooling sequence.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FractionalAvgPoolGrad'.
        /// </param>
        /// <param name="overlapping">
        ///    When set to True, it means when pooling, the values at the boundary
        ///    of adjacent pooling cells are used by both cells. For example:
        ///    
        ///    <c>index  0  1  2  3  4</c>
        ///    
        ///    <c>value  20 5  16 3  7</c>
        ///    
        ///    If the pooling sequence is [0, 2, 4], then 16, at index 2 will be used twice.
        ///    The result would be [41/3, 26/3] for fractional avg pooling.
        /// </param>
        /// <returns>
        ///    4-D.  Gradients w.r.t. the input of <c>fractional_avg_pool</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Unlike FractionalMaxPoolGrad, we don't need to find arg_max for
        ///    FractionalAvgPoolGrad, we just need to evenly back-propagate each element of
        ///    out_backprop to those indices that form the same pooling cell. Therefore, we
        ///    just need to know the shape of original input tensor, instead of the whole
        ///    tensor.
        /// </remarks>
        public static Tensor fractional_avg_pool_grad (Tensor orig_input_tensor_shape, Tensor out_backprop, Tensor row_pooling_sequence, Tensor col_pooling_sequence, bool? overlapping = null, string name = "FractionalAvgPoolGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["orig_input_tensor_shape"] = orig_input_tensor_shape;
            dict["out_backprop"] = out_backprop;
            dict["row_pooling_sequence"] = row_pooling_sequence;
            dict["col_pooling_sequence"] = col_pooling_sequence;
            if (overlapping.HasValue)
                dict["overlapping"] = overlapping.Value;
            var op = _op_def_lib._apply_op_helper("FractionalAvgPoolGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Performs fractional max pooling on the input.
        /// </summary>
        /// <param name="value">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FractionalMaxPool'.
        /// </param>
        /// <param name="pooling_ratio">
        ///    Optional argument
        ///    Pooling ratio for each dimension of <c>value</c>, currently only
        ///    supports row and col dimension and should be &amp;gt;= 1.0. For example, a valid
        ///    pooling ratio looks like [1.0, 1.44, 1.73, 1.0]. The first and last elements
        ///    must be 1.0 because we don't allow pooling on batch and channels
        ///    dimensions. 1.44 and 1.73 are pooling ratio on height and width dimensions
        ///    respectively.
        /// </param>
        /// <param name="pseudo_random">
        ///    When set to True, generates the pooling sequence in a
        ///    pseudorandom fashion, otherwise, in a random fashion. Check paper [Benjamin
        ///    Graham, Fractional Max-Pooling](http://arxiv.org/abs/1412.6071) for
        ///    difference between pseudorandom and random.
        /// </param>
        /// <param name="overlapping">
        ///    When set to True, it means when pooling, the values at the boundary
        ///    of adjacent pooling cells are used by both cells. For example:
        ///    
        ///    <c>index  0  1  2  3  4</c>
        ///    
        ///    <c>value  20 5  16 3  7</c>
        ///    
        ///    If the pooling sequence is [0, 2, 4], then 16, at index 2 will be used twice.
        ///    The result would be [20, 16] for fractional max pooling.
        /// </param>
        /// <param name="deterministic">
        ///    When set to True, a fixed pooling region will be used when
        ///    iterating over a FractionalMaxPool node in the computation graph. Mainly used
        ///    in unit test to make FractionalMaxPool deterministic.
        /// </param>
        /// <param name="seed">
        ///    If either seed or seed2 are set to be non-zero, the random number
        ///    generator is seeded by the given seed.  Otherwise, it is seeded by a
        ///    random seed.
        /// </param>
        /// <param name="seed2">
        ///    An second seed to avoid seed collision.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output : output tensor after fractional max pooling.
        ///    row_pooling_sequence : row pooling sequence, needed to calculate gradient.
        ///    col_pooling_sequence : column pooling sequence, needed to calculate gradient.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Fractional max pooling is slightly different than regular max pooling.  In
        ///    regular max pooling, you downsize an input set by taking the maximum value of
        ///    smaller N x N subsections of the set (often 2x2), and try to reduce the set by
        ///    a factor of N, where N is an integer.  Fractional max pooling, as you might
        ///    expect from the word "fractional", means that the overall reduction ratio N
        ///    does not have to be an integer.
        ///    
        ///    The sizes of the pooling regions are generated randomly but are fairly uniform.
        ///    For example, let's look at the height dimension, and the constraints on the
        ///    list of rows that will be pool boundaries.
        ///    
        ///    First we define the following:
        ///    
        ///    1.  input_row_length : the number of rows from the input set
        ///    2.  output_row_length : which will be smaller than the input
        ///    3.  alpha = input_row_length / output_row_length : our reduction ratio
        ///    4.  K = floor(alpha)
        ///    5.  row_pooling_sequence : this is the result list of pool boundary rows
        ///    
        ///    Then, row_pooling_sequence should satisfy:
        ///    
        ///    1.  a[0] = 0 : the first value of the sequence is 0
        ///    2.  a[end] = input_row_length : the last value of the sequence is the size
        ///    3.  K &amp;lt;= (a[i+1] - a[i]) &amp;lt;= K+1 : all intervals are K or K+1 size
        ///    4.  length(row_pooling_sequence) = output_row_length+1
        ///    
        ///    For more details on fractional max pooling, see this paper:
        ///    [Benjamin Graham, Fractional Max-Pooling](http://arxiv.org/abs/1412.6071)
        /// </remarks>
        public static (Tensor output, Tensor row_pooling_sequence, Tensor col_pooling_sequence) fractional_max_pool (Tensor value, float[] pooling_ratio, bool? pseudo_random = null, bool? overlapping = null, bool? deterministic = null, int? seed = null, int? seed2 = null, string name = "FractionalMaxPool")
        {
            var dict = new Dictionary<string, object>();
            dict["value"] = value;
            dict["pooling_ratio"] = pooling_ratio;
            if (pseudo_random.HasValue)
                dict["pseudo_random"] = pseudo_random.Value;
            if (overlapping.HasValue)
                dict["overlapping"] = overlapping.Value;
            if (deterministic.HasValue)
                dict["deterministic"] = deterministic.Value;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("FractionalMaxPool", name: name, keywords: dict);
            int _idx = 0;
            var output = op.outputs[_idx++];
            var row_pooling_sequence = op.outputs[_idx++];
            var col_pooling_sequence = op.outputs[_idx++];
            return (output, row_pooling_sequence, col_pooling_sequence);
        }

        /// <summary>
        ///    Computes gradient of the FractionalMaxPool function.
        /// </summary>
        /// <param name="orig_input">
        ///    Original input for <c>fractional_max_pool</c>
        /// </param>
        /// <param name="orig_output">
        ///    Original output for <c>fractional_max_pool</c>
        /// </param>
        /// <param name="out_backprop">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.  Gradients
        ///    w.r.t. the output of <c>fractional_max_pool</c>.
        /// </param>
        /// <param name="row_pooling_sequence">
        ///    row pooling sequence, form pooling region with
        ///    col_pooling_sequence.
        /// </param>
        /// <param name="col_pooling_sequence">
        ///    column pooling sequence, form pooling region with
        ///    row_pooling sequence.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FractionalMaxPoolGrad'.
        /// </param>
        /// <param name="overlapping">
        ///    When set to True, it means when pooling, the values at the boundary
        ///    of adjacent pooling cells are used by both cells. For example:
        ///    
        ///    <c>index  0  1  2  3  4</c>
        ///    
        ///    <c>value  20 5  16 3  7</c>
        ///    
        ///    If the pooling sequence is [0, 2, 4], then 16, at index 2 will be used twice.
        ///    The result would be [20, 16] for fractional max pooling.
        /// </param>
        /// <returns>
        ///    4-D.  Gradients w.r.t. the input of <c>fractional_max_pool</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor fractional_max_pool_grad (Tensor orig_input, Tensor orig_output, Tensor out_backprop, Tensor row_pooling_sequence, Tensor col_pooling_sequence, bool? overlapping = null, string name = "FractionalMaxPoolGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["orig_input"] = orig_input;
            dict["orig_output"] = orig_output;
            dict["out_backprop"] = out_backprop;
            dict["row_pooling_sequence"] = row_pooling_sequence;
            dict["col_pooling_sequence"] = col_pooling_sequence;
            if (overlapping.HasValue)
                dict["overlapping"] = overlapping.Value;
            var op = _op_def_lib._apply_op_helper("FractionalMaxPoolGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Batch normalization.
        /// </summary>
        /// <param name="x">
        ///    A 4D Tensor for input data.
        /// </param>
        /// <param name="scale">
        ///    A 1D Tensor for scaling factor, to scale the normalized x.
        /// </param>
        /// <param name="offset">
        ///    A 1D Tensor for offset, to shift to the normalized x.
        /// </param>
        /// <param name="mean">
        ///    A 1D Tensor for population mean. Used for inference only;
        ///    must be empty for training.
        /// </param>
        /// <param name="variance">
        ///    A 1D Tensor for population variance. Used for inference only;
        ///    must be empty for training.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FusedBatchNorm'.
        /// </param>
        /// <param name="epsilon">
        ///    A small float number added to the variance of x.
        /// </param>
        /// <param name="data_format">
        ///    The data format for x and y. Either "NHWC" (default) or "NCHW".
        /// </param>
        /// <param name="is_training">
        ///    A bool value to indicate the operation is for training (default)
        ///    or inference.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    y : A 4D Tensor for output data.
        ///    batch_mean : A 1D Tensor for the computed batch mean, to be used by TensorFlow
        ///    to compute the running mean.
        ///    batch_variance : A 1D Tensor for the computed batch variance, to be used by
        ///    TensorFlow to compute the running variance.
        ///    reserve_space_1 : A 1D Tensor for the computed batch mean, to be reused
        ///    in the gradient computation.
        ///    reserve_space_2 : A 1D Tensor for the computed batch variance (inverted variance
        ///    in the cuDNN case), to be reused in the gradient computation.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Note that the size of 4D Tensors are defined by either "NHWC" or "NCHW".
        ///    The size of 1D Tensors matches the dimension C of the 4D Tensors.
        /// </remarks>
        public static (Tensor y, Tensor batch_mean, Tensor batch_variance, Tensor reserve_space_1, Tensor reserve_space_2) fused_batch_norm (Tensor x, Tensor scale, Tensor offset, Tensor mean, Tensor variance, float? epsilon = null, string data_format = null, bool? is_training = null, string name = "FusedBatchNorm")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["scale"] = scale;
            dict["offset"] = offset;
            dict["mean"] = mean;
            dict["variance"] = variance;
            if (epsilon.HasValue)
                dict["epsilon"] = epsilon.Value;
            if (data_format != null)
                dict["data_format"] = data_format;
            if (is_training.HasValue)
                dict["is_training"] = is_training.Value;
            var op = _op_def_lib._apply_op_helper("FusedBatchNorm", name: name, keywords: dict);
            int _idx = 0;
            var y = op.outputs[_idx++];
            var batch_mean = op.outputs[_idx++];
            var batch_variance = op.outputs[_idx++];
            var reserve_space_1 = op.outputs[_idx++];
            var reserve_space_2 = op.outputs[_idx++];
            return (y, batch_mean, batch_variance, reserve_space_1, reserve_space_2);
        }

        /// <summary>
        ///    Gradient for batch normalization.
        /// </summary>
        /// <param name="y_backprop">
        ///    A 4D Tensor for the gradient with respect to y.
        /// </param>
        /// <param name="x">
        ///    A 4D Tensor for input data.
        /// </param>
        /// <param name="scale">
        ///    A 1D Tensor for scaling factor, to scale the normalized x.
        /// </param>
        /// <param name="reserve_space_1">
        ///    When is_training is True, a 1D Tensor for the computed batch
        ///    mean to be reused in gradient computation. When is_training is
        ///    False, a 1D Tensor for the population mean to be reused in both
        ///    1st and 2nd order gradient computation.
        /// </param>
        /// <param name="reserve_space_2">
        ///    When is_training is True, a 1D Tensor for the computed batch
        ///    variance (inverted variance in the cuDNN case) to be reused in
        ///    gradient computation. When is_training is False, a 1D Tensor
        ///    for the population variance to be reused in both 1st and 2nd
        ///    order gradient computation.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FusedBatchNormGrad'.
        /// </param>
        /// <param name="epsilon">
        ///    A small float number added to the variance of x.
        /// </param>
        /// <param name="data_format">
        ///    The data format for y_backprop, x, x_backprop.
        ///    Either "NHWC" (default) or "NCHW".
        /// </param>
        /// <param name="is_training">
        ///    A bool value to indicate the operation is for training (default)
        ///    or inference.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    x_backprop : A 4D Tensor for the gradient with respect to x.
        ///    scale_backprop : A 1D Tensor for the gradient with respect to scale.
        ///    offset_backprop : A 1D Tensor for the gradient with respect to offset.
        ///    reserve_space_3 : Unused placeholder to match the mean input in FusedBatchNorm.
        ///    reserve_space_4 : Unused placeholder to match the variance input
        ///    in FusedBatchNorm.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Note that the size of 4D Tensors are defined by either "NHWC" or "NCHW".
        ///    The size of 1D Tensors matches the dimension C of the 4D Tensors.
        /// </remarks>
        public static (Tensor x_backprop, Tensor scale_backprop, Tensor offset_backprop, Tensor reserve_space_3, Tensor reserve_space_4) fused_batch_norm_grad (Tensor y_backprop, Tensor x, Tensor scale, Tensor reserve_space_1, Tensor reserve_space_2, float? epsilon = null, string data_format = null, bool? is_training = null, string name = "FusedBatchNormGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["y_backprop"] = y_backprop;
            dict["x"] = x;
            dict["scale"] = scale;
            dict["reserve_space_1"] = reserve_space_1;
            dict["reserve_space_2"] = reserve_space_2;
            if (epsilon.HasValue)
                dict["epsilon"] = epsilon.Value;
            if (data_format != null)
                dict["data_format"] = data_format;
            if (is_training.HasValue)
                dict["is_training"] = is_training.Value;
            var op = _op_def_lib._apply_op_helper("FusedBatchNormGrad", name: name, keywords: dict);
            int _idx = 0;
            var x_backprop = op.outputs[_idx++];
            var scale_backprop = op.outputs[_idx++];
            var offset_backprop = op.outputs[_idx++];
            var reserve_space_3 = op.outputs[_idx++];
            var reserve_space_4 = op.outputs[_idx++];
            return (x_backprop, scale_backprop, offset_backprop, reserve_space_3, reserve_space_4);
        }

        /// <summary>
        ///    Gradient for batch normalization.
        /// </summary>
        /// <param name="y_backprop">
        ///    A 4D Tensor for the gradient with respect to y.
        /// </param>
        /// <param name="x">
        ///    A 4D Tensor for input data.
        /// </param>
        /// <param name="scale">
        ///    A 1D Tensor for scaling factor, to scale the normalized x.
        /// </param>
        /// <param name="reserve_space_1">
        ///    When is_training is True, a 1D Tensor for the computed batch
        ///    mean to be reused in gradient computation. When is_training is
        ///    False, a 1D Tensor for the population mean to be reused in both
        ///    1st and 2nd order gradient computation.
        /// </param>
        /// <param name="reserve_space_2">
        ///    When is_training is True, a 1D Tensor for the computed batch
        ///    variance (inverted variance in the cuDNN case) to be reused in
        ///    gradient computation. When is_training is False, a 1D Tensor
        ///    for the population variance to be reused in both 1st and 2nd
        ///    order gradient computation.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FusedBatchNormGradV2'.
        /// </param>
        /// <param name="epsilon">
        ///    A small float number added to the variance of x.
        /// </param>
        /// <param name="data_format">
        ///    The data format for y_backprop, x, x_backprop.
        ///    Either "NHWC" (default) or "NCHW".
        /// </param>
        /// <param name="is_training">
        ///    A bool value to indicate the operation is for training (default)
        ///    or inference.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    x_backprop : A 4D Tensor for the gradient with respect to x.
        ///    scale_backprop : A 1D Tensor for the gradient with respect to scale.
        ///    offset_backprop : A 1D Tensor for the gradient with respect to offset.
        ///    reserve_space_3 : Unused placeholder to match the mean input in FusedBatchNorm.
        ///    reserve_space_4 : Unused placeholder to match the variance input
        ///    in FusedBatchNorm.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Note that the size of 4D Tensors are defined by either "NHWC" or "NCHW".
        ///    The size of 1D Tensors matches the dimension C of the 4D Tensors.
        /// </remarks>
        public static (Tensor x_backprop, Tensor scale_backprop, Tensor offset_backprop, Tensor reserve_space_3, Tensor reserve_space_4) fused_batch_norm_grad_v2 (Tensor y_backprop, Tensor x, Tensor scale, Tensor reserve_space_1, Tensor reserve_space_2, float? epsilon = null, string data_format = null, bool? is_training = null, string name = "FusedBatchNormGradV2")
        {
            var dict = new Dictionary<string, object>();
            dict["y_backprop"] = y_backprop;
            dict["x"] = x;
            dict["scale"] = scale;
            dict["reserve_space_1"] = reserve_space_1;
            dict["reserve_space_2"] = reserve_space_2;
            if (epsilon.HasValue)
                dict["epsilon"] = epsilon.Value;
            if (data_format != null)
                dict["data_format"] = data_format;
            if (is_training.HasValue)
                dict["is_training"] = is_training.Value;
            var op = _op_def_lib._apply_op_helper("FusedBatchNormGradV2", name: name, keywords: dict);
            int _idx = 0;
            var x_backprop = op.outputs[_idx++];
            var scale_backprop = op.outputs[_idx++];
            var offset_backprop = op.outputs[_idx++];
            var reserve_space_3 = op.outputs[_idx++];
            var reserve_space_4 = op.outputs[_idx++];
            return (x_backprop, scale_backprop, offset_backprop, reserve_space_3, reserve_space_4);
        }

        /// <summary>
        ///    Batch normalization.
        /// </summary>
        /// <param name="x">
        ///    A 4D Tensor for input data.
        /// </param>
        /// <param name="scale">
        ///    A 1D Tensor for scaling factor, to scale the normalized x.
        /// </param>
        /// <param name="offset">
        ///    A 1D Tensor for offset, to shift to the normalized x.
        /// </param>
        /// <param name="mean">
        ///    A 1D Tensor for population mean. Used for inference only;
        ///    must be empty for training.
        /// </param>
        /// <param name="variance">
        ///    A 1D Tensor for population variance. Used for inference only;
        ///    must be empty for training.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FusedBatchNormV2'.
        /// </param>
        /// <param name="epsilon">
        ///    A small float number added to the variance of x.
        /// </param>
        /// <param name="data_format">
        ///    The data format for x and y. Either "NHWC" (default) or "NCHW".
        /// </param>
        /// <param name="is_training">
        ///    A bool value to indicate the operation is for training (default)
        ///    or inference.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    y : A 4D Tensor for output data.
        ///    batch_mean : A 1D Tensor for the computed batch mean, to be used by TensorFlow
        ///    to compute the running mean.
        ///    batch_variance : A 1D Tensor for the computed batch variance, to be used by
        ///    TensorFlow to compute the running variance.
        ///    reserve_space_1 : A 1D Tensor for the computed batch mean, to be reused
        ///    in the gradient computation.
        ///    reserve_space_2 : A 1D Tensor for the computed batch variance (inverted variance
        ///    in the cuDNN case), to be reused in the gradient computation.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Note that the size of 4D Tensors are defined by either "NHWC" or "NCHW".
        ///    The size of 1D Tensors matches the dimension C of the 4D Tensors.
        /// </remarks>
        public static (Tensor y, Tensor batch_mean, Tensor batch_variance, Tensor reserve_space_1, Tensor reserve_space_2) fused_batch_norm_v2 (Tensor x, Tensor scale, Tensor offset, Tensor mean, Tensor variance, float? epsilon = null, string data_format = null, bool? is_training = null, string name = "FusedBatchNormV2")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["scale"] = scale;
            dict["offset"] = offset;
            dict["mean"] = mean;
            dict["variance"] = variance;
            if (epsilon.HasValue)
                dict["epsilon"] = epsilon.Value;
            if (data_format != null)
                dict["data_format"] = data_format;
            if (is_training.HasValue)
                dict["is_training"] = is_training.Value;
            var op = _op_def_lib._apply_op_helper("FusedBatchNormV2", name: name, keywords: dict);
            int _idx = 0;
            var y = op.outputs[_idx++];
            var batch_mean = op.outputs[_idx++];
            var batch_variance = op.outputs[_idx++];
            var reserve_space_1 = op.outputs[_idx++];
            var reserve_space_2 = op.outputs[_idx++];
            return (y, batch_mean, batch_variance, reserve_space_1, reserve_space_2);
        }

        /// <summary>
        ///    Performs a padding as a preprocess during a convolution.
        /// </summary>
        /// <param name="input">
        ///    4-D with shape <c>[batch, in_height, in_width, in_channels]</c>.
        /// </param>
        /// <param name="paddings">
        ///    A two-column matrix specifying the padding sizes. The number of
        ///    rows must be the same as the rank of <c>input</c>.
        /// </param>
        /// <param name="filter">
        ///    4-D with shape
        ///    <c>[filter_height, filter_width, in_channels, out_channels]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FusedPadConv2D'.
        /// </param>
        /// <param name="mode">
        ///    Optional argument
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    1-D of length 4.  The stride of the sliding window for each dimension
        ///    of <c>input</c>. Must be in the same order as the dimension specified with format.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Similar to FusedResizeAndPadConv2d, this op allows for an optimized
        ///    implementation where the spatial padding transformation stage is fused with the
        ///    im2col lookup, but in this case without the bilinear filtering required for
        ///    resizing. Fusing the padding prevents the need to write out the intermediate
        ///    results as whole tensors, reducing memory pressure, and we can get some latency
        ///    gains by merging the transformation calculations.
        ///    The data_format attribute for Conv2D isn't supported by this op, and 'NHWC'
        ///    order is used instead.
        ///    Internally this op uses a single per-graph scratch buffer, which means that it
        ///    will block if multiple versions are being run in parallel. This is because this
        ///    operator is primarily an optimization to minimize memory usage.
        /// </remarks>
        public static Tensor fused_pad_conv2d (Tensor input, Tensor paddings, Tensor filter, string mode, int[] strides, string padding, string name = "FusedPadConv2D")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["paddings"] = paddings;
            dict["filter"] = filter;
            dict["mode"] = mode;
            dict["strides"] = strides;
            dict["padding"] = padding;
            var op = _op_def_lib._apply_op_helper("FusedPadConv2D", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Performs a resize and padding as a preprocess during a convolution.
        /// </summary>
        /// <param name="input">
        ///    4-D with shape <c>[batch, in_height, in_width, in_channels]</c>.
        /// </param>
        /// <param name="size">
        ///    A 1-D int32 Tensor of 2 elements: <c>new_height, new_width</c>.  The
        ///    new size for the images.
        /// </param>
        /// <param name="paddings">
        ///    A two-column matrix specifying the padding sizes. The number of
        ///    rows must be the same as the rank of <c>input</c>.
        /// </param>
        /// <param name="filter">
        ///    4-D with shape
        ///    <c>[filter_height, filter_width, in_channels, out_channels]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'FusedResizeAndPadConv2D'.
        /// </param>
        /// <param name="mode">
        ///    Optional argument
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    1-D of length 4.  The stride of the sliding window for each dimension
        ///    of <c>input</c>. Must be in the same order as the dimension specified with format.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="resize_align_corners">
        ///    If true, the centers of the 4 corner pixels of the input and output tensors are
        ///    aligned, preserving the values at the corner pixels. Defaults to false.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    It's often possible to do spatial transformations more efficiently as part of
        ///    the packing stage of a convolution, so this op allows for an optimized
        ///    implementation where these stages are fused together. This prevents the need to
        ///    write out the intermediate results as whole tensors, reducing memory pressure,
        ///    and we can get some latency gains by merging the transformation calculations.
        ///    The data_format attribute for Conv2D isn't supported by this op, and defaults to
        ///    'NHWC' order.
        ///    Internally this op uses a single per-graph scratch buffer, which means that it
        ///    will block if multiple versions are being run in parallel. This is because this
        ///    operator is primarily an optimization to minimize memory usage.
        /// </remarks>
        public static Tensor fused_resize_and_pad_conv2d (Tensor input, Tensor size, Tensor paddings, Tensor filter, string mode, int[] strides, string padding, bool? resize_align_corners = null, string name = "FusedResizeAndPadConv2D")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["size"] = size;
            dict["paddings"] = paddings;
            dict["filter"] = filter;
            dict["mode"] = mode;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (resize_align_corners.HasValue)
                dict["resize_align_corners"] = resize_align_corners.Value;
            var op = _op_def_lib._apply_op_helper("FusedResizeAndPadConv2D", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Gather slices from <c>params</c> according to <c>indices</c>.
        /// </summary>
        /// <param name="parameters">
        /// </param>
        /// <param name="indices">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Gather'.
        /// </param>
        /// <param name="validate_indices">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    <c>indices</c> must be an integer tensor of any dimension (usually 0-D or 1-D).
        ///    Produces an output tensor with shape <c>indices.shape + params.shape[1:]</c> where:
        ///    
        ///   <code>
        ///    # Scalar indices
        ///    output[:, ..., :] = params[indices, :, ... :]
        ///    
        ///    # Vector indices
        ///    output[i, :, ..., :] = params[indices[i], :, ... :]
        ///    
        ///    # Higher rank indices
        ///    output[i, ..., j, :, ... :] = params[indices[i, ..., j], :, ..., :]
        ///   </code>
        ///    
        ///    If <c>indices</c> is a permutation and <c>len(indices) == params.shape[0]</c> then
        ///    this operation will permute <c>params</c> accordingly.
        ///    
        ///    <c>validate_indices</c>: DEPRECATED. If this operation is assigned to CPU, values in
        ///    <c>indices</c> are always validated to be within range. If assigned to GPU,
        ///    out-of-bound indices result in safe but unspecified behavior, which may include
        ///    raising an error.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src="https://www.tensorflow.org/images/Gather.png" alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Tensor gather (Tensor parameters, Tensor indices, bool? validate_indices = null, string name = "Gather")
        {
            var dict = new Dictionary<string, object>();
            dict["params"] = parameters;
            dict["indices"] = indices;
            if (validate_indices.HasValue)
                dict["validate_indices"] = validate_indices.Value;
            var op = _op_def_lib._apply_op_helper("Gather", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Gather slices from <c>params</c> into a Tensor with shape specified by <c>indices</c>.
        /// </summary>
        /// <param name="parameters">
        ///    The tensor from which to gather values.
        /// </param>
        /// <param name="indices">
        ///    Index tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'GatherNd'.
        /// </param>
        /// <returns>
        ///    Values from <c>params</c> gathered from indices given by <c>indices</c>, with
        ///    shape <c>indices.shape[:-1] + params.shape[indices.shape[-1]:]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    <c>indices</c> is an K-dimensional integer tensor, best thought of as a
        ///    (K-1)-dimensional tensor of indices into <c>params</c>, where each element defines a
        ///    slice of <c>params</c>:
        ///    
        ///    output[\\(i_0, ..., i_{K-2}\\)] = params[indices[\\(i_0, ..., i_{K-2}\\)]]
        ///    
        ///    Whereas in <c>tf.gather</c> <c>indices</c> defines slices into the first
        ///    dimension of <c>params</c>, in <c>tf.gather_nd</c>, <c>indices</c> defines slices into the
        ///    first <c>N</c> dimensions of <c>params</c>, where <c>N = indices.shape[-1]</c>.
        ///    
        ///    The last dimension of <c>indices</c> can be at most the rank of
        ///    <c>params</c>:
        ///    
        ///    indices.shape[-1] &amp;lt;= params.rank
        ///    
        ///    The last dimension of <c>indices</c> corresponds to elements
        ///    (if <c>indices.shape[-1] == params.rank</c>) or slices
        ///    (if <c>indices.shape[-1] &amp;lt; params.rank</c>) along dimension <c>indices.shape[-1]</c>
        ///    of <c>params</c>.  The output tensor has shape
        ///    
        ///    indices.shape[:-1] + params.shape[indices.shape[-1]:]
        ///    
        ///    Note that on CPU, if an out of bound index is found, an error is returned.
        ///    On GPU, if an out of bound index is found, a 0 is stored in the
        ///    corresponding output value.
        ///    
        ///    Some examples below.
        ///    
        ///    Simple indexing into a matrix:
        ///    
        ///   <code>
        ///    indices = [[0, 0], [1, 1]]
        ///    params = [['a', 'b'], ['c', 'd']]
        ///    output = ['a', 'd']
        ///   </code>
        ///    
        ///    Slice indexing into a matrix:
        ///    
        ///   <code>
        ///    indices = [[1], [0]]
        ///    params = [['a', 'b'], ['c', 'd']]
        ///    output = [['c', 'd'], ['a', 'b']]
        ///   </code>
        ///    
        ///    Indexing into a 3-tensor:
        ///    
        ///   <code>
        ///    indices = [[1]]
        ///    params = [[['a0', 'b0'], ['c0', 'd0']],
        ///    [['a1', 'b1'], ['c1', 'd1']]]
        ///    output = [[['a1', 'b1'], ['c1', 'd1']]]
        ///    
        ///    
        ///    indices = [[0, 1], [1, 0]]
        ///    params = [[['a0', 'b0'], ['c0', 'd0']],
        ///    [['a1', 'b1'], ['c1', 'd1']]]
        ///    output = [['c0', 'd0'], ['a1', 'b1']]
        ///    
        ///    
        ///    indices = [[0, 0, 1], [1, 0, 1]]
        ///    params = [[['a0', 'b0'], ['c0', 'd0']],
        ///    [['a1', 'b1'], ['c1', 'd1']]]
        ///    output = ['b0', 'b1']
        ///   </code>
        ///    
        ///    Batched indexing into a matrix:
        ///    
        ///   <code>
        ///    indices = [[[0, 0]], [[0, 1]]]
        ///    params = [['a', 'b'], ['c', 'd']]
        ///    output = [['a'], ['b']]
        ///   </code>
        ///    
        ///    Batched slice indexing into a matrix:
        ///    
        ///   <code>
        ///    indices = [[[1]], [[0]]]
        ///    params = [['a', 'b'], ['c', 'd']]
        ///    output = [[['c', 'd']], [['a', 'b']]]
        ///   </code>
        ///    
        ///    Batched indexing into a 3-tensor:
        ///    
        ///   <code>
        ///    indices = [[[1]], [[0]]]
        ///    params = [[['a0', 'b0'], ['c0', 'd0']],
        ///    [['a1', 'b1'], ['c1', 'd1']]]
        ///    output = [[[['a1', 'b1'], ['c1', 'd1']]],
        ///    [[['a0', 'b0'], ['c0', 'd0']]]]
        ///    
        ///    indices = [[[0, 1], [1, 0]], [[0, 0], [1, 1]]]
        ///    params = [[['a0', 'b0'], ['c0', 'd0']],
        ///    [['a1', 'b1'], ['c1', 'd1']]]
        ///    output = [[['c0', 'd0'], ['a1', 'b1']],
        ///    [['a0', 'b0'], ['c1', 'd1']]]
        ///    
        ///    
        ///    indices = [[[0, 0, 1], [1, 0, 1]], [[0, 1, 1], [1, 1, 0]]]
        ///    params = [[['a0', 'b0'], ['c0', 'd0']],
        ///    [['a1', 'b1'], ['c1', 'd1']]]
        ///    output = [['b0', 'b1'], ['d0', 'c1']]
        ///   </code>
        ///    
        ///    See also <c>tf.gather</c> and <c>tf.batch_gather</c>.
        /// </remarks>
        public static Tensor gather_nd (Tensor parameters, Tensor indices, string name = "GatherNd")
        {
            var dict = new Dictionary<string, object>();
            dict["params"] = parameters;
            dict["indices"] = indices;
            var op = _op_def_lib._apply_op_helper("GatherNd", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Gather slices from <c>params</c> axis <c>axis</c> according to <c>indices</c>.
        /// </summary>
        /// <param name="parameters">
        ///    The tensor from which to gather values. Must be at least rank
        ///    <c>axis + 1</c>.
        /// </param>
        /// <param name="indices">
        ///    Index tensor. Must be in range <c>[0, params.shape[axis])</c>.
        /// </param>
        /// <param name="axis">
        ///    The axis in <c>params</c> to gather <c>indices</c> from. Defaults to the first
        ///    dimension. Supports negative indexes.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'GatherV2'.
        /// </param>
        /// <returns>
        ///    Values from <c>params</c> gathered from indices given by <c>indices</c>, with
        ///    shape <c>params.shape[:axis] + indices.shape + params.shape[axis + 1:]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    <c>indices</c> must be an integer tensor of any dimension (usually 0-D or 1-D).
        ///    Produces an output tensor with shape <c>params.shape[:axis] + indices.shape +
        ///    params.shape[axis + 1:]</c> where:
        ///    
        ///   <code>
        ///    # Scalar indices (output is rank(params) - 1).
        ///    output[a_0, ..., a_n, b_0, ..., b_n] =
        ///    params[a_0, ..., a_n, indices, b_0, ..., b_n]
        ///    
        ///    # Vector indices (output is rank(params)).
        ///    output[a_0, ..., a_n, i, b_0, ..., b_n] =
        ///    params[a_0, ..., a_n, indices[i], b_0, ..., b_n]
        ///    
        ///    # Higher rank indices (output is rank(params) + rank(indices) - 1).
        ///    output[a_0, ..., a_n, i, ..., j, b_0, ... b_n] =
        ///    params[a_0, ..., a_n, indices[i, ..., j], b_0, ..., b_n]
        ///   </code>
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src="https://www.tensorflow.org/images/Gather.png" alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        ///    
        ///    Note that on CPU, if an out of bound index is found, an error is returned.
        ///    On GPU, if an out of bound index is found, a 0 is stored in the
        ///    corresponding output value.
        ///    
        ///    See also <c>tf.batch_gather</c> and <c>tf.gather_nd</c>.
        /// </remarks>
        public static Tensor gather_v2 (Tensor parameters, Tensor indices, Tensor axis, string name = "GatherV2")
        {
            var dict = new Dictionary<string, object>();
            dict["params"] = parameters;
            dict["indices"] = indices;
            dict["axis"] = axis;
            var op = _op_def_lib._apply_op_helper("GatherV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Given a path to new and old vocabulary files, returns a remapping Tensor of
        /// </summary>
        /// <param name="new_vocab_file">
        ///    Path to the new vocab file.
        /// </param>
        /// <param name="old_vocab_file">
        ///    Path to the old vocab file.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'GenerateVocabRemapping'.
        /// </param>
        /// <param name="new_vocab_offset">
        ///    Optional argument
        ///    How many entries into the new vocab file to start reading.
        /// </param>
        /// <param name="num_new_vocab">
        ///    Optional argument
        ///    Number of entries in the new vocab file to remap.
        /// </param>
        /// <param name="old_vocab_size">
        ///    Number of entries in the old vocab file to consider.  If -1,
        ///    use the entire old vocabulary.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    remapping : A Tensor of length num_new_vocab where the element at index i
        ///    is equal to the old ID that maps to the new ID i.  This element is -1 for any
        ///    new ID that is not found in the old vocabulary.
        ///    num_present : Number of new vocab entries found in old vocab.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    length <c>num_new_vocab</c>, where <c>remapping[i]</c> contains the row number in the old
        ///    vocabulary that corresponds to row <c>i</c> in the new vocabulary (starting at line
        ///    <c>new_vocab_offset</c> and up to <c>num_new_vocab</c> entities), or <c>-1</c> if entry <c>i</c>
        ///    in the new vocabulary is not in the old vocabulary.  The old vocabulary is
        ///    constrained to the first <c>old_vocab_size</c> entries if <c>old_vocab_size</c> is not the
        ///    default value of -1.
        ///    
        ///    <c>num_vocab_offset</c> enables
        ///    use in the partitioned variable case, and should generally be set through
        ///    examining partitioning info.  The format of the files should be a text file,
        ///    with each line containing a single entity within the vocabulary.
        ///    
        ///    For example, with <c>new_vocab_file</c> a text file containing each of the following
        ///    elements on a single line: <c>[f0, f1, f2, f3]</c>, old_vocab_file = [f1, f0, f3],
        ///    <c>num_new_vocab = 3, new_vocab_offset = 1</c>, the returned remapping would be
        ///    <c>[0, -1, 2]</c>.
        ///    
        ///    The op also returns a count of how many entries in the new vocabulary
        ///    were present in the old vocabulary, which is used to calculate the number of
        ///    values to initialize in a weight matrix remapping
        ///    
        ///    This functionality can be used to remap both row vocabularies (typically,
        ///    features) and column vocabularies (typically, classes) from TensorFlow
        ///    checkpoints.  Note that the partitioning logic relies on contiguous vocabularies
        ///    corresponding to div-partitioned variables.  Moreover, the underlying remapping
        ///    uses an IndexTable (as opposed to an inexact CuckooTable), so client code should
        ///    use the corresponding index_table_from_file() as the FeatureColumn framework
        ///    does (as opposed to tf.feature_to_id(), which uses a CuckooTable).
        /// </remarks>
        public static (Tensor remapping, Tensor num_present) generate_vocab_remapping (Tensor new_vocab_file, Tensor old_vocab_file, int new_vocab_offset, int num_new_vocab, int? old_vocab_size = null, string name = "GenerateVocabRemapping")
        {
            var dict = new Dictionary<string, object>();
            dict["new_vocab_file"] = new_vocab_file;
            dict["old_vocab_file"] = old_vocab_file;
            dict["new_vocab_offset"] = new_vocab_offset;
            dict["num_new_vocab"] = num_new_vocab;
            if (old_vocab_size.HasValue)
                dict["old_vocab_size"] = old_vocab_size.Value;
            var op = _op_def_lib._apply_op_helper("GenerateVocabRemapping", name: name, keywords: dict);
            int _idx = 0;
            var remapping = op.outputs[_idx++];
            var num_present = op.outputs[_idx++];
            return (remapping, num_present);
        }

        /// <summary>
        ///    Store the input tensor in the state of the current session.
        /// </summary>
        /// <param name="value">
        ///    The tensor to be stored.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'GetSessionHandle'.
        /// </param>
        /// <returns>
        ///    The handle for the tensor stored in the session state, represented
        ///    as a string.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor get_session_handle (Tensor value, string name = "GetSessionHandle")
        {
            var dict = new Dictionary<string, object>();
            dict["value"] = value;
            var op = _op_def_lib._apply_op_helper("GetSessionHandle", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Store the input tensor in the state of the current session.
        /// </summary>
        /// <param name="value">
        ///    The tensor to be stored.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'GetSessionHandleV2'.
        /// </param>
        /// <returns>
        ///    The handle for the tensor stored in the session state, represented
        ///    as a ResourceHandle object.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor get_session_handle_v2 (Tensor value, string name = "GetSessionHandleV2")
        {
            var dict = new Dictionary<string, object>();
            dict["value"] = value;
            var op = _op_def_lib._apply_op_helper("GetSessionHandleV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Get the value of the tensor specified by its handle.
        /// </summary>
        /// <param name="handle">
        ///    The handle for a tensor stored in the session state.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'GetSessionTensor'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The type of the output value.
        /// </param>
        /// <returns>
        ///    The tensor for the given handle.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor get_session_tensor (Tensor handle, TF_DataType dtype, string name = "GetSessionTensor")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["dtype"] = dtype;
            var op = _op_def_lib._apply_op_helper("GetSessionTensor", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the truth value of (x &amp;gt; y) element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Greater'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    *NOTE*: <c>Greater</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor greater (Tensor x, Tensor y, string name = "Greater")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("Greater", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the truth value of (x &amp;gt;= y) element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'GreaterEqual'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    *NOTE*: <c>GreaterEqual</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor greater_equal (Tensor x, Tensor y, string name = "GreaterEqual")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("GreaterEqual", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Gives a guarantee to the TF runtime that the input tensor is a constant.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'GuaranteeConst'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The runtime is then free to make optimizations based on this.
        ///    
        ///    Only accepts value typed tensors as inputs and rejects resource variable handles
        ///    as input.
        ///    
        ///    Returns the input tensor without modification.
        /// </remarks>
        public static Tensor guarantee_const (Tensor input, string name = "GuaranteeConst")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("GuaranteeConst", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Convert one or more images from HSV to RGB.
        /// </summary>
        /// <param name="images">
        ///    1-D or higher rank. HSV data to convert. Last dimension must be size 3.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'HSVToRGB'.
        /// </param>
        /// <returns>
        ///    <c>images</c> converted to RGB.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Outputs a tensor of the same shape as the <c>images</c> tensor, containing the RGB
        ///    value of the pixels. The output is only well defined if the value in <c>images</c>
        ///    are in <c>[0,1]</c>.
        ///    
        ///    See <c>rgb_to_hsv</c> for a description of the HSV encoding.
        /// </remarks>
        public static Tensor h_s_v_to_r_g_b (Tensor images, string name = "HSVToRGB")
        {
            var dict = new Dictionary<string, object>();
            dict["images"] = images;
            var op = _op_def_lib._apply_op_helper("HSVToRGB", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a non-initialized hash table.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'HashTable'.
        /// </param>
        /// <param name="key_dtype">
        ///    Optional argument
        ///    Type of the table keys.
        /// </param>
        /// <param name="value_dtype">
        ///    Optional argument
        ///    Type of the table values.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this table is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this table is shared under the given name across
        ///    multiple sessions.
        /// </param>
        /// <param name="use_node_name_sharing">
        ///    If true and shared_name is empty, the table is shared
        ///    using the node name.
        /// </param>
        /// <returns>
        ///    Handle to a table.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op creates a hash table, specifying the type of its keys and values.
        ///    Before using the table you will have to initialize it.  After initialization the
        ///    table will be immutable.
        /// </remarks>
        public static Tensor hash_table (TF_DataType key_dtype, TF_DataType value_dtype, string container = null, string shared_name = null, bool? use_node_name_sharing = null, string name = "HashTable")
        {
            var dict = new Dictionary<string, object>();
            dict["key_dtype"] = key_dtype;
            dict["value_dtype"] = value_dtype;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            if (use_node_name_sharing.HasValue)
                dict["use_node_name_sharing"] = use_node_name_sharing.Value;
            var op = _op_def_lib._apply_op_helper("HashTable", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a non-initialized hash table.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'HashTableV2'.
        /// </param>
        /// <param name="key_dtype">
        ///    Optional argument
        ///    Type of the table keys.
        /// </param>
        /// <param name="value_dtype">
        ///    Optional argument
        ///    Type of the table values.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this table is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this table is shared under the given name across
        ///    multiple sessions.
        /// </param>
        /// <param name="use_node_name_sharing">
        ///    If true and shared_name is empty, the table is shared
        ///    using the node name.
        /// </param>
        /// <returns>
        ///    Handle to a table.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op creates a hash table, specifying the type of its keys and values.
        ///    Before using the table you will have to initialize it.  After initialization the
        ///    table will be immutable.
        /// </remarks>
        public static Tensor hash_table_v2 (TF_DataType key_dtype, TF_DataType value_dtype, string container = null, string shared_name = null, bool? use_node_name_sharing = null, string name = "HashTableV2")
        {
            var dict = new Dictionary<string, object>();
            dict["key_dtype"] = key_dtype;
            dict["value_dtype"] = value_dtype;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            if (use_node_name_sharing.HasValue)
                dict["use_node_name_sharing"] = use_node_name_sharing.Value;
            var op = _op_def_lib._apply_op_helper("HashTableV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Return histogram of values.
        /// </summary>
        /// <param name="values">
        ///    Numeric <c>Tensor</c>.
        /// </param>
        /// <param name="value_range">
        ///    Shape [2] <c>Tensor</c> of same <c>dtype</c> as <c>values</c>.
        ///    values &amp;lt;= value_range[0] will be mapped to hist[0],
        ///    values &amp;gt;= value_range[1] will be mapped to hist[-1].
        /// </param>
        /// <param name="nbins">
        ///    Scalar <c>int32 Tensor</c>.  Number of histogram bins.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'HistogramFixedWidth'.
        /// </param>
        /// <param name="dtype">
        /// </param>
        /// <returns>
        ///    A 1-D <c>Tensor</c> holding histogram of values.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given the tensor <c>values</c>, this operation returns a rank 1 histogram counting
        ///    the number of entries in <c>values</c> that fall into every bin.  The bins are
        ///    equal width and determined by the arguments <c>value_range</c> and <c>nbins</c>.
        ///    
        ///   <code>
        ///    # Bins will be:  (-inf, 1), [1, 2), [2, 3), [3, 4), [4, inf)
        ///    nbins = 5
        ///    value_range = [0.0, 5.0]
        ///    new_values = [-1.0, 0.0, 1.5, 2.0, 5.0, 15]
        ///    
        ///    with tf.get_default_session() as sess:
        ///    hist = tf.histogram_fixed_width(new_values, value_range, nbins=5)
        ///    variables.global_variables_initializer().run()
        ///    sess.run(hist) =&amp;gt; [2, 1, 1, 0, 2]
        ///   </code>
        /// </remarks>
        public static Tensor histogram_fixed_width (Tensor values, Tensor value_range, Tensor nbins, TF_DataType? dtype = null, string name = "HistogramFixedWidth")
        {
            var dict = new Dictionary<string, object>();
            dict["values"] = values;
            dict["value_range"] = value_range;
            dict["nbins"] = nbins;
            if (dtype.HasValue)
                dict["dtype"] = dtype.Value;
            var op = _op_def_lib._apply_op_helper("HistogramFixedWidth", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Outputs a <c>Summary</c> protocol buffer with a histogram.
        /// </summary>
        /// <param name="tag">
        ///    Scalar.  Tag to use for the <c>Summary.Value</c>.
        /// </param>
        /// <param name="values">
        ///    Any shape. Values to use to build the histogram.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'HistogramSummary'.
        /// </param>
        /// <returns>
        ///    Scalar. Serialized <c>Summary</c> protocol buffer.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The generated
        ///    [<c>Summary</c>](https://www.tensorflow.org/code/tensorflow/core/framework/summary.proto)
        ///    has one summary value containing a histogram for <c>values</c>.
        ///    
        ///    This op reports an <c>InvalidArgument</c> error if any value is not finite.
        /// </remarks>
        public static Tensor histogram_summary (Tensor tag, Tensor values, string name = "HistogramSummary")
        {
            var dict = new Dictionary<string, object>();
            dict["tag"] = tag;
            dict["values"] = values;
            var op = _op_def_lib._apply_op_helper("HistogramSummary", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns a constant tensor on the host. Only for writing C++ tests.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'HostConst'.
        /// </param>
        /// <param name="value">
        ///    Optional argument
        ///    Attr <c>value</c> is the tensor to return.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor host_const (Tensor value, TF_DataType dtype, string name = "HostConst")
        {
            var dict = new Dictionary<string, object>();
            dict["value"] = value;
            dict["dtype"] = dtype;
            var op = _op_def_lib._apply_op_helper("HostConst", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Inverse fast Fourier transform.
        /// </summary>
        /// <param name="input">
        ///    A complex64 tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'IFFT'.
        /// </param>
        /// <returns>
        ///    A complex64 tensor of the same shape as <c>input</c>. The inner-most
        ///    dimension of <c>input</c> is replaced with its inverse 1D Fourier transform.
        ///    
        ///    @compatibility(numpy)
        ///    Equivalent to np.fft.ifft
        ///    @end_compatibility
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Computes the inverse 1-dimensional discrete Fourier transform over the
        ///    inner-most dimension of <c>input</c>.
        /// </remarks>
        public static Tensor i_f_f_t (Tensor input, string name = "IFFT")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("IFFT", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Inverse 2D fast Fourier transform.
        /// </summary>
        /// <param name="input">
        ///    A complex64 tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'IFFT2D'.
        /// </param>
        /// <returns>
        ///    A complex64 tensor of the same shape as <c>input</c>. The inner-most 2
        ///    dimensions of <c>input</c> are replaced with their inverse 2D Fourier transform.
        ///    
        ///    @compatibility(numpy)
        ///    Equivalent to np.fft.ifft2
        ///    @end_compatibility
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Computes the inverse 2-dimensional discrete Fourier transform over the
        ///    inner-most 2 dimensions of <c>input</c>.
        /// </remarks>
        public static Tensor i_f_f_t2d (Tensor input, string name = "IFFT2D")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("IFFT2D", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Inverse 3D fast Fourier transform.
        /// </summary>
        /// <param name="input">
        ///    A complex64 tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'IFFT3D'.
        /// </param>
        /// <returns>
        ///    A complex64 tensor of the same shape as <c>input</c>. The inner-most 3
        ///    dimensions of <c>input</c> are replaced with their inverse 3D Fourier transform.
        ///    
        ///    @compatibility(numpy)
        ///    Equivalent to np.fft.ifftn with 3 dimensions.
        ///    @end_compatibility
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Computes the inverse 3-dimensional discrete Fourier transform over the
        ///    inner-most 3 dimensions of <c>input</c>.
        /// </remarks>
        public static Tensor i_f_f_t3d (Tensor input, string name = "IFFT3D")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("IFFT3D", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Inverse real-valued fast Fourier transform.
        /// </summary>
        /// <param name="input">
        ///    A complex64 tensor.
        /// </param>
        /// <param name="fft_length">
        ///    An int32 tensor of shape [1]. The FFT length.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'IRFFT'.
        /// </param>
        /// <returns>
        ///    A float32 tensor of the same rank as <c>input</c>. The inner-most
        ///    dimension of <c>input</c> is replaced with the <c>fft_length</c> samples of its inverse
        ///    1D Fourier transform.
        ///    
        ///    @compatibility(numpy)
        ///    Equivalent to np.fft.irfft
        ///    @end_compatibility
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Computes the inverse 1-dimensional discrete Fourier transform of a real-valued
        ///    signal over the inner-most dimension of <c>input</c>.
        ///    
        ///    The inner-most dimension of <c>input</c> is assumed to be the result of <c>RFFT</c>: the
        ///    <c>fft_length / 2 + 1</c> unique components of the DFT of a real-valued signal. If
        ///    <c>fft_length</c> is not provided, it is computed from the size of the inner-most
        ///    dimension of <c>input</c> (<c>fft_length = 2 * (inner - 1)</c>). If the FFT length used to
        ///    compute <c>input</c> is odd, it should be provided since it cannot be inferred
        ///    properly.
        ///    
        ///    Along the axis <c>IRFFT</c> is computed on, if <c>fft_length / 2 + 1</c> is smaller
        ///    than the corresponding dimension of <c>input</c>, the dimension is cropped. If it is
        ///    larger, the dimension is padded with zeros.
        /// </remarks>
        public static Tensor i_r_f_f_t (Tensor input, Tensor fft_length, string name = "IRFFT")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["fft_length"] = fft_length;
            var op = _op_def_lib._apply_op_helper("IRFFT", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Inverse 2D real-valued fast Fourier transform.
        /// </summary>
        /// <param name="input">
        ///    A complex64 tensor.
        /// </param>
        /// <param name="fft_length">
        ///    An int32 tensor of shape [2]. The FFT length for each dimension.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'IRFFT2D'.
        /// </param>
        /// <returns>
        ///    A float32 tensor of the same rank as <c>input</c>. The inner-most 2
        ///    dimensions of <c>input</c> are replaced with the <c>fft_length</c> samples of their
        ///    inverse 2D Fourier transform.
        ///    
        ///    @compatibility(numpy)
        ///    Equivalent to np.fft.irfft2
        ///    @end_compatibility
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Computes the inverse 2-dimensional discrete Fourier transform of a real-valued
        ///    signal over the inner-most 2 dimensions of <c>input</c>.
        ///    
        ///    The inner-most 2 dimensions of <c>input</c> are assumed to be the result of <c>RFFT2D</c>:
        ///    The inner-most dimension contains the <c>fft_length / 2 + 1</c> unique components of
        ///    the DFT of a real-valued signal. If <c>fft_length</c> is not provided, it is computed
        ///    from the size of the inner-most 2 dimensions of <c>input</c>. If the FFT length used
        ///    to compute <c>input</c> is odd, it should be provided since it cannot be inferred
        ///    properly.
        ///    
        ///    Along each axis <c>IRFFT2D</c> is computed on, if <c>fft_length</c> (or
        ///    <c>fft_length / 2 + 1</c> for the inner-most dimension) is smaller than the
        ///    corresponding dimension of <c>input</c>, the dimension is cropped. If it is larger,
        ///    the dimension is padded with zeros.
        /// </remarks>
        public static Tensor i_r_f_f_t2d (Tensor input, Tensor fft_length, string name = "IRFFT2D")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["fft_length"] = fft_length;
            var op = _op_def_lib._apply_op_helper("IRFFT2D", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Inverse 3D real-valued fast Fourier transform.
        /// </summary>
        /// <param name="input">
        ///    A complex64 tensor.
        /// </param>
        /// <param name="fft_length">
        ///    An int32 tensor of shape [3]. The FFT length for each dimension.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'IRFFT3D'.
        /// </param>
        /// <returns>
        ///    A float32 tensor of the same rank as <c>input</c>. The inner-most 3
        ///    dimensions of <c>input</c> are replaced with the <c>fft_length</c> samples of their
        ///    inverse 3D real Fourier transform.
        ///    
        ///    @compatibility(numpy)
        ///    Equivalent to np.irfftn with 3 dimensions.
        ///    @end_compatibility
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Computes the inverse 3-dimensional discrete Fourier transform of a real-valued
        ///    signal over the inner-most 3 dimensions of <c>input</c>.
        ///    
        ///    The inner-most 3 dimensions of <c>input</c> are assumed to be the result of <c>RFFT3D</c>:
        ///    The inner-most dimension contains the <c>fft_length / 2 + 1</c> unique components of
        ///    the DFT of a real-valued signal. If <c>fft_length</c> is not provided, it is computed
        ///    from the size of the inner-most 3 dimensions of <c>input</c>. If the FFT length used
        ///    to compute <c>input</c> is odd, it should be provided since it cannot be inferred
        ///    properly.
        ///    
        ///    Along each axis <c>IRFFT3D</c> is computed on, if <c>fft_length</c> (or
        ///    <c>fft_length / 2 + 1</c> for the inner-most dimension) is smaller than the
        ///    corresponding dimension of <c>input</c>, the dimension is cropped. If it is larger,
        ///    the dimension is padded with zeros.
        /// </remarks>
        public static Tensor i_r_f_f_t3d (Tensor input, Tensor fft_length, string name = "IRFFT3D")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["fft_length"] = fft_length;
            var op = _op_def_lib._apply_op_helper("IRFFT3D", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Return a tensor with the same shape and contents as the input tensor or value.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Identity'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor identity (Tensor input, string name = "Identity")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("Identity", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns a list of tensors with the same shapes and contents as the input
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'IdentityN'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    tensors.
        ///    
        ///    This op can be used to override the gradient for complicated functions. For
        ///    example, suppose y = f(x) and we wish to apply a custom function g for backprop
        ///    such that dx = g(dy). In Python,
        ///    
        ///   <code>
        ///    with tf.get_default_graph().gradient_override_map(
        ///    {'IdentityN': 'OverrideGradientWithG'}):
        ///    y, _ = identity_n([f(x), x])
        ///    
        ///    @tf.RegisterGradient('OverrideGradientWithG')
        ///    def ApplyG(op, dy, _):
        ///    return [None, g(dy)]  # Do not backprop to f(x).
        ///   </code>
        /// </remarks>
        public static Tensor[] identity_n (Tensor[] input, string name = "IdentityN")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("IdentityN", name: name, keywords: dict);
            int _idx = 0;
            var output = Enumerable.Range(0, op.OutputListLength("output")).Select(_ => op.outputs[_idx++]).ToArray();
            return (output);
        }

        /// <summary>
        ///    A Reader that outputs the queued work as both the key and value.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'IdentityReader'.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this reader is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this reader is named in the given bucket
        ///    with this shared_name. Otherwise, the node name is used instead.
        /// </param>
        /// <returns>
        ///    The handle to reference the Reader.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    To use, enqueue strings in a Queue.  ReaderRead will take the front
        ///    work string and output (work, work).
        /// </remarks>
        public static Tensor identity_reader (string container = null, string shared_name = null, string name = "IdentityReader")
        {
            var dict = new Dictionary<string, object>();
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("IdentityReader", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A Reader that outputs the queued work as both the key and value.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'IdentityReaderV2'.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this reader is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this reader is named in the given bucket
        ///    with this shared_name. Otherwise, the node name is used instead.
        /// </param>
        /// <returns>
        ///    The handle to reference the Reader.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    To use, enqueue strings in a Queue.  ReaderRead will take the front
        ///    work string and output (work, work).
        /// </remarks>
        public static Tensor identity_reader_v2 (string container = null, string shared_name = null, string name = "IdentityReaderV2")
        {
            var dict = new Dictionary<string, object>();
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("IdentityReaderV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Compute the lower regularized incomplete Gamma function <c>P(a, x)</c>.
        /// </summary>
        /// <param name="a">
        /// </param>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Igamma'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The lower regularized incomplete Gamma function is defined as:
        ///    
        ///    
        ///    \\(P(a, x) = gamma(a, x) / Gamma(a) = 1 - Q(a, x)\\)
        ///    
        ///    where
        ///    
        ///    \\(gamma(a, x) = \\int_{0}^{x} t^{a-1} exp(-t) dt\\)
        ///    
        ///    is the lower incomplete Gamma function.
        ///    
        ///    Note, above <c>Q(a, x)</c> (<c>Igammac</c>) is the upper regularized complete
        ///    Gamma function.
        /// </remarks>
        public static Tensor igamma (Tensor a, Tensor x, string name = "Igamma")
        {
            var dict = new Dictionary<string, object>();
            dict["a"] = a;
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Igamma", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradient of <c>igamma(a, x)</c> wrt <c>a</c>.
        /// </summary>
        /// <param name="a">
        /// </param>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'IgammaGradA'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor igamma_grad_a (Tensor a, Tensor x, string name = "IgammaGradA")
        {
            var dict = new Dictionary<string, object>();
            dict["a"] = a;
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("IgammaGradA", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Compute the upper regularized incomplete Gamma function <c>Q(a, x)</c>.
        /// </summary>
        /// <param name="a">
        /// </param>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Igammac'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The upper regularized incomplete Gamma function is defined as:
        ///    
        ///    \\(Q(a, x) = Gamma(a, x) / Gamma(a) = 1 - P(a, x)\\)
        ///    
        ///    where
        ///    
        ///    \\(Gamma(a, x) = int_{x}^{\infty} t^{a-1} exp(-t) dt\\)
        ///    
        ///    is the upper incomplete Gama function.
        ///    
        ///    Note, above <c>P(a, x)</c> (<c>Igamma</c>) is the lower regularized complete
        ///    Gamma function.
        /// </remarks>
        public static Tensor igammac (Tensor a, Tensor x, string name = "Igammac")
        {
            var dict = new Dictionary<string, object>();
            dict["a"] = a;
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Igammac", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the imaginary part of a complex number.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Imag'.
        /// </param>
        /// <param name="Tout">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given a tensor <c>input</c> of complex numbers, this operation returns a tensor of
        ///    type <c>float</c> that is the imaginary part of each element in <c>input</c>. All
        ///    elements in <c>input</c> must be complex numbers of the form \\(a + bj\\), where *a*
        ///    is the real part and *b* is the imaginary part returned by this operation.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # tensor 'input' is [-2.25 + 4.75j, 3.25 + 5.75j]
        ///    tf.imag(input) ==&amp;gt; [4.75, 5.75]
        ///   </code>
        /// </remarks>
        public static Tensor imag (Tensor input, TF_DataType? Tout = null, string name = "Imag")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (Tout.HasValue)
                dict["Tout"] = Tout.Value;
            var op = _op_def_lib._apply_op_helper("Imag", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Outputs a <c>Summary</c> protocol buffer with images.
        /// </summary>
        /// <param name="tag">
        ///    Scalar. Used to build the <c>tag</c> attribute of the summary values.
        /// </param>
        /// <param name="tensor">
        ///    4-D of shape <c>[batch_size, height, width, channels]</c> where
        ///    <c>channels</c> is 1, 3, or 4.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ImageSummary'.
        /// </param>
        /// <param name="max_images">
        ///    Max number of batch elements to generate images for.
        /// </param>
        /// <param name="bad_color">
        ///    Color to use for pixels with non-finite values.
        /// </param>
        /// <returns>
        ///    Scalar. Serialized <c>Summary</c> protocol buffer.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The summary has up to <c>max_images</c> summary values containing images. The
        ///    images are built from <c>tensor</c> which must be 4-D with shape <c>[batch_size,
        ///    height, width, channels]</c> and where <c>channels</c> can be:
        ///    
        ///    *  1: <c>tensor</c> is interpreted as Grayscale.
        ///    *  3: <c>tensor</c> is interpreted as RGB.
        ///    *  4: <c>tensor</c> is interpreted as RGBA.
        ///    
        ///    The images have the same number of channels as the input tensor. For float
        ///    input, the values are normalized one image at a time to fit in the range
        ///    <c>[0, 255]</c>.  <c>uint8</c> values are unchanged.  The op uses two different
        ///    normalization algorithms:
        ///    
        ///    *  If the input values are all positive, they are rescaled so the largest one
        ///    is 255.
        ///    
        ///    *  If any input value is negative, the values are shifted so input value 0.0
        ///    is at 127.  They are then rescaled so that either the smallest value is 0,
        ///    or the largest one is 255.
        ///    
        ///    The <c>tag</c> argument is a scalar <c>Tensor</c> of type <c>string</c>.  It is used to
        ///    build the <c>tag</c> of the summary values:
        ///    
        ///    *  If <c>max_images</c> is 1, the summary value tag is '*tag*/image'.
        ///    *  If <c>max_images</c> is greater than 1, the summary value tags are
        ///    generated sequentially as '*tag*/image/0', '*tag*/image/1', etc.
        ///    
        ///    The <c>bad_color</c> argument is the color to use in the generated images for
        ///    non-finite input values.  It is a <c>uint8</c> 1-D tensor of length <c>channels</c>.
        ///    Each element must be in the range <c>[0, 255]</c> (It represents the value of a
        ///    pixel in the output image).  Non-finite values in the input tensor are
        ///    replaced by this tensor in the output image.  The default value is the color
        ///    red.
        /// </remarks>
        public static Tensor image_summary (Tensor tag, Tensor tensor, int? max_images = null, Tensor bad_color = null, string name = "ImageSummary")
        {
            var dict = new Dictionary<string, object>();
            dict["tag"] = tag;
            dict["tensor"] = tensor;
            if (max_images.HasValue)
                dict["max_images"] = max_images.Value;
            if (bad_color != null)
                dict["bad_color"] = bad_color;
            var op = _op_def_lib._apply_op_helper("ImageSummary", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns immutable tensor from memory region.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ImmutableConst'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    Type of the returned tensor.
        /// </param>
        /// <param name="shape">
        ///    Optional argument
        ///    Shape of the returned tensor.
        /// </param>
        /// <param name="memory_region_name">
        ///    Optional argument
        ///    Name of readonly memory region used by the tensor, see
        ///    NewReadOnlyMemoryRegionFromFile in tensorflow::Env.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The current implementation memmaps the tensor from a file.
        /// </remarks>
        public static Tensor immutable_const (TF_DataType dtype, TensorShape shape, string memory_region_name, string name = "ImmutableConst")
        {
            var dict = new Dictionary<string, object>();
            dict["dtype"] = dtype;
            dict["shape"] = shape;
            dict["memory_region_name"] = memory_region_name;
            var op = _op_def_lib._apply_op_helper("ImmutableConst", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Says whether the targets are in the top <c>K</c> predictions.
        /// </summary>
        /// <param name="predictions">
        ///    A <c>batch_size</c> x <c>classes</c> tensor.
        /// </param>
        /// <param name="targets">
        ///    A <c>batch_size</c> vector of class ids.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'InTopK'.
        /// </param>
        /// <param name="k">
        ///    Optional argument
        ///    Number of top elements to look at for computing precision.
        /// </param>
        /// <returns>
        ///    Computed Precision at <c>k</c> as a <c>bool Tensor</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This outputs a <c>batch_size</c> bool array, an entry <c>out[i]</c> is <c>true</c> if the
        ///    prediction for the target class is among the top <c>k</c> predictions among
        ///    all predictions for example <c>i</c>. Note that the behavior of <c>InTopK</c> differs
        ///    from the <c>TopK</c> op in its handling of ties; if multiple classes have the
        ///    same prediction value and straddle the top-<c>k</c> boundary, all of those
        ///    classes are considered to be in the top <c>k</c>.
        ///    
        ///    More formally, let
        ///    
        ///    \\(predictions_i\\) be the predictions for all classes for example <c>i</c>,
        ///    \\(targets_i\\) be the target class for example <c>i</c>,
        ///    \\(out_i\\) be the output for example <c>i</c>,
        ///    
        ///    $$out_i = predictions_{i, targets_i} \in TopKIncludingTies(predictions_i)$$
        /// </remarks>
        public static Tensor in_top_k (Tensor predictions, Tensor targets, int k, string name = "InTopK")
        {
            var dict = new Dictionary<string, object>();
            dict["predictions"] = predictions;
            dict["targets"] = targets;
            dict["k"] = k;
            var op = _op_def_lib._apply_op_helper("InTopK", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Says whether the targets are in the top <c>K</c> predictions.
        /// </summary>
        /// <param name="predictions">
        ///    A <c>batch_size</c> x <c>classes</c> tensor.
        /// </param>
        /// <param name="targets">
        ///    A <c>batch_size</c> vector of class ids.
        /// </param>
        /// <param name="k">
        ///    Number of top elements to look at for computing precision.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'InTopKV2'.
        /// </param>
        /// <returns>
        ///    Computed precision at <c>k</c> as a <c>bool Tensor</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This outputs a <c>batch_size</c> bool array, an entry <c>out[i]</c> is <c>true</c> if the
        ///    prediction for the target class is among the top <c>k</c> predictions among
        ///    all predictions for example <c>i</c>. Note that the behavior of <c>InTopK</c> differs
        ///    from the <c>TopK</c> op in its handling of ties; if multiple classes have the
        ///    same prediction value and straddle the top-<c>k</c> boundary, all of those
        ///    classes are considered to be in the top <c>k</c>.
        ///    
        ///    More formally, let
        ///    
        ///    \\(predictions_i\\) be the predictions for all classes for example <c>i</c>,
        ///    \\(targets_i\\) be the target class for example <c>i</c>,
        ///    \\(out_i\\) be the output for example <c>i</c>,
        ///    
        ///    $$out_i = predictions_{i, targets_i} \in TopKIncludingTies(predictions_i)$$
        /// </remarks>
        public static Tensor in_top_k_v2 (Tensor predictions, Tensor targets, Tensor k, string name = "InTopKV2")
        {
            var dict = new Dictionary<string, object>();
            dict["predictions"] = predictions;
            dict["targets"] = targets;
            dict["k"] = k;
            var op = _op_def_lib._apply_op_helper("InTopKV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A placeholder op for a value that will be fed into the computation.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'InfeedDequeue'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The type of elements in the tensor.
        /// </param>
        /// <param name="shape">
        ///    Optional argument
        ///    The shape of the tensor.
        /// </param>
        /// <returns>
        ///    A tensor that will be provided using the infeed mechanism.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor infeed_dequeue (TF_DataType dtype, TensorShape shape, string name = "InfeedDequeue")
        {
            var dict = new Dictionary<string, object>();
            dict["dtype"] = dtype;
            dict["shape"] = shape;
            var op = _op_def_lib._apply_op_helper("InfeedDequeue", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A placeholder op for multiple values that will be fed into the computation
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'InfeedDequeueTuple'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        ///    The element types of each element in <c>outputs</c>.
        /// </param>
        /// <param name="shapes">
        ///    Optional argument
        ///    The shapes of each tensor in <c>outputs</c>.
        /// </param>
        /// <returns>
        ///    A list of tensors that will be provided using the infeed mechanism.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    simultaneously as an XLA tuple.
        /// </remarks>
        public static Tensor[] infeed_dequeue_tuple (TF_DataType[] dtypes, TensorShape[] shapes, string name = "InfeedDequeueTuple")
        {
            var dict = new Dictionary<string, object>();
            dict["dtypes"] = dtypes;
            dict["shapes"] = shapes;
            var op = _op_def_lib._apply_op_helper("InfeedDequeueTuple", name: name, keywords: dict);
            int _idx = 0;
            var outputs = Enumerable.Range(0, op.OutputListLength("outputs")).Select(_ => op.outputs[_idx++]).ToArray();
            return (outputs);
        }

        /// <summary>
        ///    An op which feeds a single Tensor value into the computation.
        /// </summary>
        /// <param name="input">
        ///    A tensor that will be provided using the infeed mechanism.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'InfeedEnqueue'.
        /// </param>
        /// <param name="shape">
        ///    The shape of the tensor.
        /// </param>
        /// <param name="device_ordinal">
        ///    The TPU device to use. This should be -1 when the Op
        ///    is running on a TPU device, and &amp;gt;= 0 when the Op is running on the CPU
        ///    device.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation infeed_enqueue (Tensor input, TensorShape shape = null, int? device_ordinal = null, string name = "InfeedEnqueue")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (shape != null)
                dict["shape"] = shape;
            if (device_ordinal.HasValue)
                dict["device_ordinal"] = device_ordinal.Value;
            var op = _op_def_lib._apply_op_helper("InfeedEnqueue", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    An op which feeds multiple Tensor values into the computation as an XLA tuple.
        /// </summary>
        /// <param name="inputs">
        ///    A list of tensors that will be provided using the infeed mechanism.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'InfeedEnqueueTuple'.
        /// </param>
        /// <param name="shapes">
        ///    Optional argument
        ///    The shapes of each tensor in <c>inputs</c>.
        /// </param>
        /// <param name="device_ordinal">
        ///    The TPU device to use. This should be -1 when the Op
        ///    is running on a TPU device, and &amp;gt;= 0 when the Op is running on the CPU
        ///    device.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation infeed_enqueue_tuple (Tensor[] inputs, TensorShape[] shapes, int? device_ordinal = null, string name = "InfeedEnqueueTuple")
        {
            var dict = new Dictionary<string, object>();
            dict["inputs"] = inputs;
            dict["shapes"] = shapes;
            if (device_ordinal.HasValue)
                dict["device_ordinal"] = device_ordinal.Value;
            var op = _op_def_lib._apply_op_helper("InfeedEnqueueTuple", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Table initializer that takes two tensors for keys and values respectively.
        /// </summary>
        /// <param name="table_handle">
        ///    Handle to a table which will be initialized.
        /// </param>
        /// <param name="keys">
        ///    Keys of type Tkey.
        /// </param>
        /// <param name="values">
        ///    Values of type Tval.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'InitializeTable'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation initialize_table (Tensor table_handle, Tensor keys, Tensor values, string name = "InitializeTable")
        {
            var dict = new Dictionary<string, object>();
            dict["table_handle"] = table_handle;
            dict["keys"] = keys;
            dict["values"] = values;
            var op = _op_def_lib._apply_op_helper("InitializeTable", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Initializes a table from a text file.
        /// </summary>
        /// <param name="table_handle">
        ///    Handle to a table which will be initialized.
        /// </param>
        /// <param name="filename">
        ///    Filename of a vocabulary text file.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'InitializeTableFromTextFile'.
        /// </param>
        /// <param name="key_index">
        ///    Optional argument
        ///    Column index in a line to get the table <c>key</c> values from.
        /// </param>
        /// <param name="value_index">
        ///    Optional argument
        ///    Column index that represents information of a line to get the table
        ///    <c>value</c> values from.
        /// </param>
        /// <param name="vocab_size">
        ///    Number of elements of the file, use -1 if unknown.
        /// </param>
        /// <param name="delimiter">
        ///    Delimiter to separate fields in a line.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    It inserts one key-value pair into the table for each line of the file.
        ///    The key and value is extracted from the whole line content, elements from the
        ///    split line based on <c>delimiter</c> or the line number (starting from zero).
        ///    Where to extract the key and value from a line is specified by <c>key_index</c> and
        ///    <c>value_index</c>.
        ///    
        ///    - A value of -1 means use the line number(starting from zero), expects <c>int64</c>.
        ///    - A value of -2 means use the whole line content, expects <c>string</c>.
        ///    - A value &amp;gt;= 0 means use the index (starting at zero) of the split line based
        ///    on <c>delimiter</c>.
        /// </remarks>
        public static Operation initialize_table_from_text_file (Tensor table_handle, Tensor filename, int key_index, int value_index, int? vocab_size = null, string delimiter = null, string name = "InitializeTableFromTextFile")
        {
            var dict = new Dictionary<string, object>();
            dict["table_handle"] = table_handle;
            dict["filename"] = filename;
            dict["key_index"] = key_index;
            dict["value_index"] = value_index;
            if (vocab_size.HasValue)
                dict["vocab_size"] = vocab_size.Value;
            if (delimiter != null)
                dict["delimiter"] = delimiter;
            var op = _op_def_lib._apply_op_helper("InitializeTableFromTextFile", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Initializes a table from a text file.
        /// </summary>
        /// <param name="table_handle">
        ///    Handle to a table which will be initialized.
        /// </param>
        /// <param name="filename">
        ///    Filename of a vocabulary text file.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'InitializeTableFromTextFileV2'.
        /// </param>
        /// <param name="key_index">
        ///    Optional argument
        ///    Column index in a line to get the table <c>key</c> values from.
        /// </param>
        /// <param name="value_index">
        ///    Optional argument
        ///    Column index that represents information of a line to get the table
        ///    <c>value</c> values from.
        /// </param>
        /// <param name="vocab_size">
        ///    Number of elements of the file, use -1 if unknown.
        /// </param>
        /// <param name="delimiter">
        ///    Delimiter to separate fields in a line.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    It inserts one key-value pair into the table for each line of the file.
        ///    The key and value is extracted from the whole line content, elements from the
        ///    split line based on <c>delimiter</c> or the line number (starting from zero).
        ///    Where to extract the key and value from a line is specified by <c>key_index</c> and
        ///    <c>value_index</c>.
        ///    
        ///    - A value of -1 means use the line number(starting from zero), expects <c>int64</c>.
        ///    - A value of -2 means use the whole line content, expects <c>string</c>.
        ///    - A value &amp;gt;= 0 means use the index (starting at zero) of the split line based
        ///    on <c>delimiter</c>.
        /// </remarks>
        public static Operation initialize_table_from_text_file_v2 (Tensor table_handle, Tensor filename, int key_index, int value_index, int? vocab_size = null, string delimiter = null, string name = "InitializeTableFromTextFileV2")
        {
            var dict = new Dictionary<string, object>();
            dict["table_handle"] = table_handle;
            dict["filename"] = filename;
            dict["key_index"] = key_index;
            dict["value_index"] = value_index;
            if (vocab_size.HasValue)
                dict["vocab_size"] = vocab_size.Value;
            if (delimiter != null)
                dict["delimiter"] = delimiter;
            var op = _op_def_lib._apply_op_helper("InitializeTableFromTextFileV2", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Table initializer that takes two tensors for keys and values respectively.
        /// </summary>
        /// <param name="table_handle">
        ///    Handle to a table which will be initialized.
        /// </param>
        /// <param name="keys">
        ///    Keys of type Tkey.
        /// </param>
        /// <param name="values">
        ///    Values of type Tval.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'InitializeTableV2'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation initialize_table_v2 (Tensor table_handle, Tensor keys, Tensor values, string name = "InitializeTableV2")
        {
            var dict = new Dictionary<string, object>();
            dict["table_handle"] = table_handle;
            dict["keys"] = keys;
            dict["values"] = values;
            var op = _op_def_lib._apply_op_helper("InitializeTableV2", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Adds v into specified rows of x.
        ///    
        ///    Computes y = x; y[i, :] += v; return y.
        /// </summary>
        /// <param name="x">
        ///    A <c>Tensor</c> of type T.
        /// </param>
        /// <param name="i">
        ///    A vector. Indices into the left-most dimension of <c>x</c>.
        /// </param>
        /// <param name="v">
        ///    A <c>Tensor</c> of type T. Same dimension sizes as x except the first dimension, which must be the same as i's size.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'InplaceAdd'.
        /// </param>
        /// <returns>
        ///    A <c>Tensor</c> of type T. An alias of <c>x</c>. The content of <c>y</c> is undefined if there are duplicates in <c>i</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor inplace_add (Tensor x, Tensor i, Tensor v, string name = "InplaceAdd")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["i"] = i;
            dict["v"] = v;
            var op = _op_def_lib._apply_op_helper("InplaceAdd", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Subtracts <c>v</c> into specified rows of <c>x</c>.
        ///    
        ///    Computes y = x; y[i, :] -= v; return y.
        /// </summary>
        /// <param name="x">
        ///    A <c>Tensor</c> of type T.
        /// </param>
        /// <param name="i">
        ///    A vector. Indices into the left-most dimension of <c>x</c>.
        /// </param>
        /// <param name="v">
        ///    A <c>Tensor</c> of type T. Same dimension sizes as x except the first dimension, which must be the same as i's size.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'InplaceSub'.
        /// </param>
        /// <returns>
        ///    A <c>Tensor</c> of type T. An alias of <c>x</c>. The content of <c>y</c> is undefined if there are duplicates in <c>i</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor inplace_sub (Tensor x, Tensor i, Tensor v, string name = "InplaceSub")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["i"] = i;
            dict["v"] = v;
            var op = _op_def_lib._apply_op_helper("InplaceSub", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Updates specified rows with values in <c>v</c>.
        ///    
        ///    Computes <c>x[i, :] = v; return x</c>.
        /// </summary>
        /// <param name="x">
        ///    A tensor of type <c>T</c>.
        /// </param>
        /// <param name="i">
        ///    A vector. Indices into the left-most dimension of <c>x</c>.
        /// </param>
        /// <param name="v">
        ///    A <c>Tensor</c> of type T. Same dimension sizes as x except the first dimension, which must be the same as i's size.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'InplaceUpdate'.
        /// </param>
        /// <returns>
        ///    A <c>Tensor</c> of type T. An alias of <c>x</c>. The content of <c>y</c> is undefined if there are duplicates in <c>i</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor inplace_update (Tensor x, Tensor i, Tensor v, string name = "InplaceUpdate")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["i"] = i;
            dict["v"] = v;
            var op = _op_def_lib._apply_op_helper("InplaceUpdate", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the reciprocal of x element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Inv'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    I.e., \\(y = 1 / x\\).
        /// </remarks>
        public static Tensor inv (Tensor x, string name = "Inv")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Inv", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradient for the inverse of <c>x</c> wrt its input.
        /// </summary>
        /// <param name="y">
        /// </param>
        /// <param name="dy">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'InvGrad'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Specifically, <c>grad = -dy * y*y</c>, where <c>y = 1/x</c>, and <c>dy</c>
        ///    is the corresponding input gradient.
        /// </remarks>
        public static Tensor inv_grad (Tensor y, Tensor dy, string name = "InvGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["y"] = y;
            dict["dy"] = dy;
            var op = _op_def_lib._apply_op_helper("InvGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Flips all bits elementwise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Invert'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The result will have exactly those bits set, that are not set in <c>x</c>. The
        ///    computation is performed on the underlying representation of x.
        /// </remarks>
        public static Tensor invert (Tensor x, string name = "Invert")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Invert", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the inverse permutation of a tensor.
        /// </summary>
        /// <param name="x">
        ///    1-D.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'InvertPermutation'.
        /// </param>
        /// <returns>
        ///    1-D.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation computes the inverse of an index permutation. It takes a 1-D
        ///    integer tensor <c>x</c>, which represents the indices of a zero-based array, and
        ///    swaps each value with its index position. In other words, for an output tensor
        ///    <c>y</c> and an input tensor <c>x</c>, this operation computes the following:
        ///    
        ///    <c>y[x[i]] = i for i in [0, 1, ..., len(x) - 1]</c>
        ///    
        ///    The values must include 0. There can be no duplicate values or negative values.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # tensor <c>x</c> is [3, 4, 0, 2, 1]
        ///    invert_permutation(x) ==&amp;gt; [2, 4, 3, 0, 1]
        ///   </code>
        /// </remarks>
        public static Tensor invert_permutation (Tensor x, string name = "InvertPermutation")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("InvertPermutation", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Checks whether a tree ensemble has been initialized.
        /// </summary>
        /// <param name="tree_ensemble_handle">
        ///    Handle to the tree ensemble resouce.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'IsBoostedTreesEnsembleInitialized'.
        /// </param>
        /// <returns>
        ///    output boolean on whether it is initialized or not.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor is_boosted_trees_ensemble_initialized (Tensor tree_ensemble_handle, string name = "IsBoostedTreesEnsembleInitialized")
        {
            var dict = new Dictionary<string, object>();
            dict["tree_ensemble_handle"] = tree_ensemble_handle;
            var op = _op_def_lib._apply_op_helper("IsBoostedTreesEnsembleInitialized", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns which elements of x are finite.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'IsFinite'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    @compatibility(numpy)
        ///    Equivalent to np.isfinite
        ///    @end_compatibility
        /// </remarks>
        public static Tensor is_finite (Tensor x, string name = "IsFinite")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("IsFinite", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns which elements of x are Inf.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'IsInf'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    @compatibility(numpy)
        ///    Equivalent to np.isinf
        ///    @end_compatibility
        /// </remarks>
        public static Tensor is_inf (Tensor x, string name = "IsInf")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("IsInf", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns which elements of x are NaN.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'IsNan'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    @compatibility(numpy)
        ///    Equivalent to np.isnan
        ///    @end_compatibility
        /// </remarks>
        public static Tensor is_nan (Tensor x, string name = "IsNan")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("IsNan", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Checks whether a tensor has been initialized.
        /// </summary>
        /// <param name="referecne">
        ///    Should be from a <c>Variable</c> node. May be uninitialized.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'IsVariableInitialized'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Outputs boolean scalar indicating whether the tensor has been initialized.
        /// </remarks>
        public static Tensor is_variable_initialized (Tensor referecne, string name = "IsVariableInitialized")
        {
            var dict = new Dictionary<string, object>();
            dict["ref"] = referecne;
            var op = _op_def_lib._apply_op_helper("IsVariableInitialized", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A container for an iterator resource.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Iterator'.
        /// </param>
        /// <param name="shared_name">
        ///    Optional argument
        /// </param>
        /// <param name="container">
        ///    Optional argument
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    A handle to the iterator that can be passed to a "MakeIterator"
        ///    or "IteratorGetNext" op.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor iterator (string shared_name, string container, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "Iterator")
        {
            var dict = new Dictionary<string, object>();
            dict["shared_name"] = shared_name;
            dict["container"] = container;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("Iterator", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Converts the given string representing a handle to an iterator to a resource.
        /// </summary>
        /// <param name="string_handle">
        ///    A string representation of the given handle.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'IteratorFromStringHandle'.
        /// </param>
        /// <param name="output_types">
        ///    If specified, defines the type of each tuple component in an
        ///    element produced by the resulting iterator.
        /// </param>
        /// <param name="output_shapes">
        ///    If specified, defines the shape of each tuple component in an
        ///    element produced by the resulting iterator.
        /// </param>
        /// <returns>
        ///    A handle to an iterator resource.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor iterator_from_string_handle (Tensor string_handle, TF_DataType[] output_types = null, TensorShape[] output_shapes = null, string name = "IteratorFromStringHandle")
        {
            var dict = new Dictionary<string, object>();
            dict["string_handle"] = string_handle;
            if (output_types != null)
                dict["output_types"] = output_types;
            if (output_shapes != null)
                dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("IteratorFromStringHandle", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Gets the next output from the given iterator .
        /// </summary>
        /// <param name="iterator">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'IteratorGetNext'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor[] iterator_get_next (Tensor iterator, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "IteratorGetNext")
        {
            var dict = new Dictionary<string, object>();
            dict["iterator"] = iterator;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("IteratorGetNext", name: name, keywords: dict);
            int _idx = 0;
            var components = Enumerable.Range(0, op.OutputListLength("components")).Select(_ => op.outputs[_idx++]).ToArray();
            return (components);
        }

        /// <summary>
        ///    Gets the next output from the given iterator as an Optional variant.
        /// </summary>
        /// <param name="iterator">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'IteratorGetNextAsOptional'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor iterator_get_next_as_optional (Tensor iterator, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "IteratorGetNextAsOptional")
        {
            var dict = new Dictionary<string, object>();
            dict["iterator"] = iterator;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("IteratorGetNextAsOptional", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Gets the next output from the given iterator.
        /// </summary>
        /// <param name="iterator">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'IteratorGetNextSync'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation is a synchronous version IteratorGetNext. It should only be used
        ///    in situations where the iterator does not block the calling thread, or where
        ///    the calling thread is not a member of the thread pool used to execute parallel
        ///    operations (e.g. in eager mode).
        /// </remarks>
        public static Tensor[] iterator_get_next_sync (Tensor iterator, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "IteratorGetNextSync")
        {
            var dict = new Dictionary<string, object>();
            dict["iterator"] = iterator;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("IteratorGetNextSync", name: name, keywords: dict);
            int _idx = 0;
            var components = Enumerable.Range(0, op.OutputListLength("components")).Select(_ => op.outputs[_idx++]).ToArray();
            return (components);
        }

        /// <summary>
        ///    Converts the given <c>resource_handle</c> representing an iterator to a string.
        /// </summary>
        /// <param name="resource_handle">
        ///    A handle to an iterator resource.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'IteratorToStringHandle'.
        /// </param>
        /// <returns>
        ///    A string representation of the given handle.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor iterator_to_string_handle (Tensor resource_handle, string name = "IteratorToStringHandle")
        {
            var dict = new Dictionary<string, object>();
            dict["resource_handle"] = resource_handle;
            var op = _op_def_lib._apply_op_helper("IteratorToStringHandle", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    L2 Loss.
        /// </summary>
        /// <param name="t">
        ///    Typically 2-D, but may have any dimensions.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'L2Loss'.
        /// </param>
        /// <returns>
        ///    0-D.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Computes half the L2 norm of a tensor without the <c>sqrt</c>:
        ///    
        ///    output = sum(t ** 2) / 2
        /// </remarks>
        public static Tensor l2loss (Tensor t, string name = "L2Loss")
        {
            var dict = new Dictionary<string, object>();
            dict["t"] = t;
            var op = _op_def_lib._apply_op_helper("L2Loss", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A Reader that outputs the records from a LMDB file.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LMDBReader'.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this reader is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this reader is named in the given bucket
        ///    with this shared_name. Otherwise, the node name is used instead.
        /// </param>
        /// <returns>
        ///    The handle to reference the Reader.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor l_m_d_b_reader (string container = null, string shared_name = null, string name = "LMDBReader")
        {
            var dict = new Dictionary<string, object>();
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("LMDBReader", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Local Response Normalization.
        /// </summary>
        /// <param name="input">
        ///    4-D.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LRN'.
        /// </param>
        /// <param name="depth_radius">
        ///    0-D.  Half-width of the 1-D normalization window.
        /// </param>
        /// <param name="bias">
        ///    An offset (usually positive to avoid dividing by 0).
        /// </param>
        /// <param name="alpha">
        ///    A scale factor, usually positive.
        /// </param>
        /// <param name="beta">
        ///    An exponent.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The 4-D <c>input</c> tensor is treated as a 3-D array of 1-D vectors (along the last
        ///    dimension), and each vector is normalized independently.  Within a given vector,
        ///    each component is divided by the weighted, squared sum of inputs within
        ///    <c>depth_radius</c>.  In detail,
        ///    
        ///    sqr_sum[a, b, c, d] =
        ///    sum(input[a, b, c, d - depth_radius : d + depth_radius + 1] ** 2)
        ///    output = input / (bias + alpha * sqr_sum) ** beta
        ///    
        ///    For details, see [Krizhevsky et al., ImageNet classification with deep
        ///    convolutional neural networks (NIPS 2012)](http://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks).
        /// </remarks>
        public static Tensor l_r_n (Tensor input, int? depth_radius = null, float? bias = null, float? alpha = null, float? beta = null, string name = "LRN")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (depth_radius.HasValue)
                dict["depth_radius"] = depth_radius.Value;
            if (bias.HasValue)
                dict["bias"] = bias.Value;
            if (alpha.HasValue)
                dict["alpha"] = alpha.Value;
            if (beta.HasValue)
                dict["beta"] = beta.Value;
            var op = _op_def_lib._apply_op_helper("LRN", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Gradients for Local Response Normalization.
        /// </summary>
        /// <param name="input_grads">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.
        /// </param>
        /// <param name="input_image">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.
        /// </param>
        /// <param name="output_image">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LRNGrad'.
        /// </param>
        /// <param name="depth_radius">
        ///    A depth radius.
        /// </param>
        /// <param name="bias">
        ///    An offset (usually &amp;gt; 0 to avoid dividing by 0).
        /// </param>
        /// <param name="alpha">
        ///    A scale factor, usually positive.
        /// </param>
        /// <param name="beta">
        ///    An exponent.
        /// </param>
        /// <returns>
        ///    The gradients for LRN.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor l_r_n_grad (Tensor input_grads, Tensor input_image, Tensor output_image, int? depth_radius = null, float? bias = null, float? alpha = null, float? beta = null, string name = "LRNGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["input_grads"] = input_grads;
            dict["input_image"] = input_image;
            dict["output_image"] = output_image;
            if (depth_radius.HasValue)
                dict["depth_radius"] = depth_radius.Value;
            if (bias.HasValue)
                dict["bias"] = bias.Value;
            if (alpha.HasValue)
                dict["alpha"] = alpha.Value;
            if (beta.HasValue)
                dict["beta"] = beta.Value;
            var op = _op_def_lib._apply_op_helper("LRNGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Records the latency of producing <c>input_dataset</c> elements in a StatsAggregator.
        /// </summary>
        /// <param name="input_dataset">
        /// </param>
        /// <param name="tag">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LatencyStatsDataset'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor latency_stats_dataset (Tensor input_dataset, Tensor tag, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "LatencyStatsDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["tag"] = tag;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("LatencyStatsDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Generates labels for candidate sampling with a learned unigram distribution.
        /// </summary>
        /// <param name="true_classes">
        ///    A batch_size * num_true matrix, in which each row contains the
        ///    IDs of the num_true target_classes in the corresponding original label.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LearnedUnigramCandidateSampler'.
        /// </param>
        /// <param name="num_true">
        ///    Optional argument
        ///    Number of true labels per context.
        /// </param>
        /// <param name="num_sampled">
        ///    Optional argument
        ///    Number of candidates to randomly sample.
        /// </param>
        /// <param name="unique">
        ///    Optional argument
        ///    If unique is true, we sample with rejection, so that all sampled
        ///    candidates in a batch are unique. This requires some approximation to
        ///    estimate the post-rejection sampling probabilities.
        /// </param>
        /// <param name="range_max">
        ///    Optional argument
        ///    The sampler will sample integers from the interval [0, range_max).
        /// </param>
        /// <param name="seed">
        ///    If either seed or seed2 are set to be non-zero, the random number
        ///    generator is seeded by the given seed.  Otherwise, it is seeded by a
        ///    random seed.
        /// </param>
        /// <param name="seed2">
        ///    An second seed to avoid seed collision.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    sampled_candidates : A vector of length num_sampled, in which each element is
        ///    the ID of a sampled candidate.
        ///    true_expected_count : A batch_size * num_true matrix, representing
        ///    the number of times each candidate is expected to occur in a batch
        ///    of sampled candidates. If unique=true, then this is a probability.
        ///    sampled_expected_count : A vector of length num_sampled, for each sampled
        ///    candidate representing the number of times the candidate is expected
        ///    to occur in a batch of sampled candidates.  If unique=true, then this is a
        ///    probability.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    See explanations of candidate sampling and the data formats at
        ///    go/candidate-sampling.
        ///    
        ///    For each batch, this op picks a single set of sampled candidate labels.
        ///    
        ///    The advantages of sampling candidates per-batch are simplicity and the
        ///    possibility of efficient dense matrix multiplication. The disadvantage is that
        ///    the sampled candidates must be chosen independently of the context and of the
        ///    true labels.
        /// </remarks>
        public static (Tensor sampled_candidates, Tensor true_expected_count, Tensor sampled_expected_count) learned_unigram_candidate_sampler (Tensor true_classes, int num_true, int num_sampled, bool unique, int range_max, int? seed = null, int? seed2 = null, string name = "LearnedUnigramCandidateSampler")
        {
            var dict = new Dictionary<string, object>();
            dict["true_classes"] = true_classes;
            dict["num_true"] = num_true;
            dict["num_sampled"] = num_sampled;
            dict["unique"] = unique;
            dict["range_max"] = range_max;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("LearnedUnigramCandidateSampler", name: name, keywords: dict);
            int _idx = 0;
            var sampled_candidates = op.outputs[_idx++];
            var true_expected_count = op.outputs[_idx++];
            var sampled_expected_count = op.outputs[_idx++];
            return (sampled_candidates, true_expected_count, sampled_expected_count);
        }

        /// <summary>
        ///    Elementwise computes the bitwise left-shift of <c>x</c> and <c>y</c>.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LeftShift'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    If <c>y</c> is negative, or greater than or equal to the width of <c>x</c> in bits the
        ///    result is implementation defined.
        /// </remarks>
        public static Tensor left_shift (Tensor x, Tensor y, string name = "LeftShift")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("LeftShift", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the truth value of (x &amp;lt; y) element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Less'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    *NOTE*: <c>Less</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor less (Tensor x, Tensor y, string name = "Less")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("Less", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the truth value of (x &amp;lt;= y) element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LessEqual'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    *NOTE*: <c>LessEqual</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor less_equal (Tensor x, Tensor y, string name = "LessEqual")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("LessEqual", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the log of the absolute value of <c>Gamma(x)</c> element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Lgamma'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor lgamma (Tensor x, string name = "Lgamma")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Lgamma", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Generates values in an interval.
        /// </summary>
        /// <param name="start">
        ///    0-D tensor. First entry in the range.
        /// </param>
        /// <param name="stop">
        ///    0-D tensor. Last entry in the range.
        /// </param>
        /// <param name="num">
        ///    0-D tensor. Number of values to generate.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LinSpace'.
        /// </param>
        /// <returns>
        ///    1-D. The generated values.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    A sequence of <c>num</c> evenly-spaced values are generated beginning at <c>start</c>.
        ///    If <c>num &amp;gt; 1</c>, the values in the sequence increase by <c>stop - start / num - 1</c>,
        ///    so that the last one is exactly <c>stop</c>.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    tf.linspace(10.0, 12.0, 3, name="linspace") =&amp;gt; [ 10.0  11.0  12.0]
        ///   </code>
        /// </remarks>
        public static Tensor lin_space (Tensor start, Tensor stop, Tensor num, string name = "LinSpace")
        {
            var dict = new Dictionary<string, object>();
            dict["start"] = start;
            dict["stop"] = stop;
            dict["num"] = num;
            var op = _op_def_lib._apply_op_helper("LinSpace", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the difference between two lists of numbers or strings.
        /// </summary>
        /// <param name="x">
        ///    1-D. Values to keep.
        /// </param>
        /// <param name="y">
        ///    1-D. Values to remove.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ListDiff'.
        /// </param>
        /// <param name="out_idx">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output : 1-D. Values present in <c>x</c> but not in <c>y</c>.
        ///    idx : 1-D. Positions of <c>x</c> values preserved in <c>out</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Given a list <c>x</c> and a list <c>y</c>, this operation returns a list <c>out</c> that
        ///    represents all values that are in <c>x</c> but not in <c>y</c>. The returned list <c>out</c>
        ///    is sorted in the same order that the numbers appear in <c>x</c> (duplicates are
        ///    preserved). This operation also returns a list <c>idx</c> that represents the
        ///    position of each <c>out</c> element in <c>x</c>. In other words:
        ///    
        ///    <c>out[i] = x[idx[i]] for i in [0, 1, ..., len(out) - 1]</c>
        ///    
        ///    For example, given this input:
        ///    
        ///   <code>
        ///    x = [1, 2, 3, 4, 5, 6]
        ///    y = [1, 3, 5]
        ///   </code>
        ///    
        ///    This operation would return:
        ///    
        ///   <code>
        ///    out ==&amp;gt; [2, 4, 6]
        ///    idx ==&amp;gt; [1, 3, 5]
        ///   </code>
        /// </remarks>
        public static (Tensor output, Tensor idx) list_diff (Tensor x, Tensor y, TF_DataType? out_idx = null, string name = "ListDiff")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            if (out_idx.HasValue)
                dict["out_idx"] = out_idx.Value;
            var op = _op_def_lib._apply_op_helper("ListDiff", name: name, keywords: dict);
            int _idx = 0;
            var output = op.outputs[_idx++];
            var idx = op.outputs[_idx++];
            return (output, idx);
        }

        /// <summary>
        ///    Loads a 2-D (matrix) <c>Tensor</c> with name <c>old_tensor_name</c> from the checkpoint
        /// </summary>
        /// <param name="ckpt_path">
        ///    Path to the TensorFlow checkpoint (version 2, <c>TensorBundle</c>) from
        ///    which the old matrix <c>Tensor</c> will be loaded.
        /// </param>
        /// <param name="old_tensor_name">
        ///    Name of the 2-D <c>Tensor</c> to load from checkpoint.
        /// </param>
        /// <param name="row_remapping">
        ///    An int <c>Tensor</c> of row remappings (generally created by
        ///    <c>generate_vocab_remapping</c>).  Even if no row remapping is needed, this must
        ///    still be an index-valued Tensor (e.g. [0, 1, 2, ...]), or a shifted
        ///    index-valued <c>Tensor</c> (e.g. [8, 9, 10, ...], for partitioned <c>Variables</c>).
        /// </param>
        /// <param name="col_remapping">
        ///    An int <c>Tensor</c> of column remappings (generally created by
        ///    <c>generate_vocab_remapping</c>).  May be a size-0 <c>Tensor</c> if only row remapping
        ///    is to be done (e.g. column ordering is the same).
        /// </param>
        /// <param name="initializing_values">
        ///    A float <c>Tensor</c> containing  values to fill in for cells
        ///    in the output matrix that are not loaded from the checkpoint. Length must be
        ///    exactly the same as the number of missing / new cells.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LoadAndRemapMatrix'.
        /// </param>
        /// <param name="num_rows">
        ///    Optional argument
        ///    Number of rows (length of the 1st dimension) in the output matrix.
        /// </param>
        /// <param name="num_cols">
        ///    Optional argument
        ///    Number of columns (length of the 2nd dimension) in the output matrix.
        /// </param>
        /// <param name="max_rows_in_memory">
        ///    The maximum number of rows to load from the checkpoint at
        ///    once. If less than or equal to 0, the entire matrix will be loaded into
        ///    memory. Setting this arg trades increased disk reads for lower memory usage.
        /// </param>
        /// <returns>
        ///    Output matrix containing existing values loaded from the
        ///    checkpoint, and with any missing values filled in from initializing_values.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    at <c>ckpt_path</c> and potentially reorders its rows and columns using the
        ///    specified remappings.
        ///    
        ///    Most users should use one of the wrapper initializers (such as
        ///    <c>tf.contrib.framework.load_and_remap_matrix_initializer</c>) instead of this
        ///    function directly.
        ///    
        ///    The remappings are 1-D tensors with the following properties:
        ///    
        ///    * <c>row_remapping</c> must have exactly <c>num_rows</c> entries. Row <c>i</c> of the output
        ///    matrix will be initialized from the row corresponding to index
        ///    <c>row_remapping[i]</c> in the old <c>Tensor</c> from the checkpoint.
        ///    * <c>col_remapping</c> must have either 0 entries (indicating that no column
        ///    reordering is needed) or <c>num_cols</c> entries. If specified, column <c>j</c> of the
        ///    output matrix will be initialized from the column corresponding to index
        ///    <c>col_remapping[j]</c> in the old <c>Tensor</c> from the checkpoint.
        ///    * A value of -1 in either of the remappings signifies a "missing" entry. In that
        ///    case, values from the <c>initializing_values</c> tensor will be used to fill that
        ///    missing row or column. If <c>row_remapping</c> has <c>r</c> missing entries and
        ///    <c>col_remapping</c> has <c>c</c> missing entries, then the following condition must be
        ///    true:
        ///    
        ///    <c>(r * num_cols) + (c * num_rows) - (r * c) == len(initializing_values)</c>
        ///    
        ///    The remapping tensors can be generated using the GenerateVocabRemapping op.
        ///    
        ///    As an example, with row_remapping = [1, 0, -1], col_remapping = [0, 2, -1],
        ///    initializing_values = [0.5, -0.5, 0.25, -0.25, 42], and w(i, j) representing
        ///    the value from row i, column j of the old tensor in the checkpoint, the output
        ///    matrix will look like the following:
        ///    
        ///    [[w(1, 0),  w(1, 2),  0.5],
        ///    [w(0, 0),  w(0, 2), -0.5],
        ///    [0.25,    -0.25,      42]]
        /// </remarks>
        public static Tensor load_and_remap_matrix (Tensor ckpt_path, Tensor old_tensor_name, Tensor row_remapping, Tensor col_remapping, Tensor initializing_values, int num_rows, int num_cols, int? max_rows_in_memory = null, string name = "LoadAndRemapMatrix")
        {
            var dict = new Dictionary<string, object>();
            dict["ckpt_path"] = ckpt_path;
            dict["old_tensor_name"] = old_tensor_name;
            dict["row_remapping"] = row_remapping;
            dict["col_remapping"] = col_remapping;
            dict["initializing_values"] = initializing_values;
            dict["num_rows"] = num_rows;
            dict["num_cols"] = num_cols;
            if (max_rows_in_memory.HasValue)
                dict["max_rows_in_memory"] = max_rows_in_memory.Value;
            var op = _op_def_lib._apply_op_helper("LoadAndRemapMatrix", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes natural logarithm of x element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Log'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    I.e., \\(y = \log_e x\\).
        /// </remarks>
        public static Tensor log (Tensor x, string name = "Log")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Log", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes natural logarithm of (1 + x) element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Log1p'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    I.e., \\(y = \log_e (1 + x)\\).
        /// </remarks>
        public static Tensor log1p (Tensor x, string name = "Log1p")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Log1p", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the sign and the log of the absolute value of the determinant of
        /// </summary>
        /// <param name="input">
        ///    Shape is <c>[N, M, M]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LogMatrixDeterminant'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    sign : The signs of the log determinants of the inputs. Shape is <c>[N]</c>.
        ///    log_abs_determinant : The logs of the absolute values of the determinants
        ///    of the N input matrices.  Shape is <c>[N]</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    one or more square matrices.
        ///    
        ///    The input is a tensor of shape <c>[N, M, M]</c> whose inner-most 2 dimensions
        ///    form square matrices. The outputs are two tensors containing the signs and
        ///    absolute values of the log determinants for all N input submatrices
        ///    <c>[..., :, :]</c> such that the determinant = sign*exp(log_abs_determinant).
        ///    The log_abs_determinant is computed as det(P)*sum(log(diag(LU))) where LU
        ///    is the LU decomposition of the input and P is the corresponding
        ///    permutation matrix.
        /// </remarks>
        public static (Tensor sign, Tensor log_abs_determinant) log_matrix_determinant (Tensor input, string name = "LogMatrixDeterminant")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("LogMatrixDeterminant", name: name, keywords: dict);
            int _idx = 0;
            var sign = op.outputs[_idx++];
            var log_abs_determinant = op.outputs[_idx++];
            return (sign, log_abs_determinant);
        }

        /// <summary>
        ///    Computes log softmax activations.
        /// </summary>
        /// <param name="logits">
        ///    2-D with shape <c>[batch_size, num_classes]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LogSoftmax'.
        /// </param>
        /// <returns>
        ///    Same shape as <c>logits</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    For each batch <c>i</c> and class <c>j</c> we have
        ///    
        ///    logsoftmax[i, j] = logits[i, j] - log(sum(exp(logits[i])))
        /// </remarks>
        public static Tensor log_softmax (Tensor logits, string name = "LogSoftmax")
        {
            var dict = new Dictionary<string, object>();
            dict["logits"] = logits;
            var op = _op_def_lib._apply_op_helper("LogSoftmax", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Generates labels for candidate sampling with a log-uniform distribution.
        /// </summary>
        /// <param name="true_classes">
        ///    A batch_size * num_true matrix, in which each row contains the
        ///    IDs of the num_true target_classes in the corresponding original label.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LogUniformCandidateSampler'.
        /// </param>
        /// <param name="num_true">
        ///    Optional argument
        ///    Number of true labels per context.
        /// </param>
        /// <param name="num_sampled">
        ///    Optional argument
        ///    Number of candidates to randomly sample.
        /// </param>
        /// <param name="unique">
        ///    Optional argument
        ///    If unique is true, we sample with rejection, so that all sampled
        ///    candidates in a batch are unique. This requires some approximation to
        ///    estimate the post-rejection sampling probabilities.
        /// </param>
        /// <param name="range_max">
        ///    Optional argument
        ///    The sampler will sample integers from the interval [0, range_max).
        /// </param>
        /// <param name="seed">
        ///    If either seed or seed2 are set to be non-zero, the random number
        ///    generator is seeded by the given seed.  Otherwise, it is seeded by a
        ///    random seed.
        /// </param>
        /// <param name="seed2">
        ///    An second seed to avoid seed collision.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    sampled_candidates : A vector of length num_sampled, in which each element is
        ///    the ID of a sampled candidate.
        ///    true_expected_count : A batch_size * num_true matrix, representing
        ///    the number of times each candidate is expected to occur in a batch
        ///    of sampled candidates. If unique=true, then this is a probability.
        ///    sampled_expected_count : A vector of length num_sampled, for each sampled
        ///    candidate representing the number of times the candidate is expected
        ///    to occur in a batch of sampled candidates.  If unique=true, then this is a
        ///    probability.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    See explanations of candidate sampling and the data formats at
        ///    go/candidate-sampling.
        ///    
        ///    For each batch, this op picks a single set of sampled candidate labels.
        ///    
        ///    The advantages of sampling candidates per-batch are simplicity and the
        ///    possibility of efficient dense matrix multiplication. The disadvantage is that
        ///    the sampled candidates must be chosen independently of the context and of the
        ///    true labels.
        /// </remarks>
        public static (Tensor sampled_candidates, Tensor true_expected_count, Tensor sampled_expected_count) log_uniform_candidate_sampler (Tensor true_classes, int num_true, int num_sampled, bool unique, int range_max, int? seed = null, int? seed2 = null, string name = "LogUniformCandidateSampler")
        {
            var dict = new Dictionary<string, object>();
            dict["true_classes"] = true_classes;
            dict["num_true"] = num_true;
            dict["num_sampled"] = num_sampled;
            dict["unique"] = unique;
            dict["range_max"] = range_max;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("LogUniformCandidateSampler", name: name, keywords: dict);
            int _idx = 0;
            var sampled_candidates = op.outputs[_idx++];
            var true_expected_count = op.outputs[_idx++];
            var sampled_expected_count = op.outputs[_idx++];
            return (sampled_candidates, true_expected_count, sampled_expected_count);
        }

        /// <summary>
        ///    Returns the truth value of x AND y element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LogicalAnd'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    *NOTE*: <c>LogicalAnd</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor logical_and (Tensor x, Tensor y, string name = "LogicalAnd")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("LogicalAnd", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the truth value of NOT x element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LogicalNot'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor logical_not (Tensor x, string name = "LogicalNot")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("LogicalNot", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the truth value of x OR y element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LogicalOr'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    *NOTE*: <c>LogicalOr</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor logical_or (Tensor x, Tensor y, string name = "LogicalOr")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("LogicalOr", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Outputs all keys and values in the table.
        /// </summary>
        /// <param name="table_handle">
        ///    Handle to the table.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LookupTableExport'.
        /// </param>
        /// <param name="Tkeys">
        ///    Optional argument
        /// </param>
        /// <param name="Tvalues">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    keys : Vector of all keys present in the table.
        ///    values : Tensor of all values in the table. Indexed in parallel with <c>keys</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor keys, Tensor values) lookup_table_export (Tensor table_handle, TF_DataType Tkeys, TF_DataType Tvalues, string name = "LookupTableExport")
        {
            var dict = new Dictionary<string, object>();
            dict["table_handle"] = table_handle;
            dict["Tkeys"] = Tkeys;
            dict["Tvalues"] = Tvalues;
            var op = _op_def_lib._apply_op_helper("LookupTableExport", name: name, keywords: dict);
            int _idx = 0;
            var keys = op.outputs[_idx++];
            var values = op.outputs[_idx++];
            return (keys, values);
        }

        /// <summary>
        ///    Outputs all keys and values in the table.
        /// </summary>
        /// <param name="table_handle">
        ///    Handle to the table.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LookupTableExportV2'.
        /// </param>
        /// <param name="Tkeys">
        ///    Optional argument
        /// </param>
        /// <param name="Tvalues">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    keys : Vector of all keys present in the table.
        ///    values : Tensor of all values in the table. Indexed in parallel with <c>keys</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor keys, Tensor values) lookup_table_export_v2 (Tensor table_handle, TF_DataType Tkeys, TF_DataType Tvalues, string name = "LookupTableExportV2")
        {
            var dict = new Dictionary<string, object>();
            dict["table_handle"] = table_handle;
            dict["Tkeys"] = Tkeys;
            dict["Tvalues"] = Tvalues;
            var op = _op_def_lib._apply_op_helper("LookupTableExportV2", name: name, keywords: dict);
            int _idx = 0;
            var keys = op.outputs[_idx++];
            var values = op.outputs[_idx++];
            return (keys, values);
        }

        /// <summary>
        ///    Looks up keys in a table, outputs the corresponding values.
        /// </summary>
        /// <param name="table_handle">
        ///    Handle to the table.
        /// </param>
        /// <param name="keys">
        ///    Any shape.  Keys to look up.
        /// </param>
        /// <param name="default_value">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LookupTableFind'.
        /// </param>
        /// <returns>
        ///    Same shape as <c>keys</c>.  Values found in the table, or <c>default_values</c>
        ///    for missing keys.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The tensor <c>keys</c> must of the same type as the keys of the table.
        ///    The output <c>values</c> is of the type of the table values.
        ///    
        ///    The scalar <c>default_value</c> is the value output for keys not present in the
        ///    table. It must also be of the same type as the table values.
        /// </remarks>
        public static Tensor lookup_table_find (Tensor table_handle, Tensor keys, Tensor default_value, string name = "LookupTableFind")
        {
            var dict = new Dictionary<string, object>();
            dict["table_handle"] = table_handle;
            dict["keys"] = keys;
            dict["default_value"] = default_value;
            var op = _op_def_lib._apply_op_helper("LookupTableFind", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Looks up keys in a table, outputs the corresponding values.
        /// </summary>
        /// <param name="table_handle">
        ///    Handle to the table.
        /// </param>
        /// <param name="keys">
        ///    Any shape.  Keys to look up.
        /// </param>
        /// <param name="default_value">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LookupTableFindV2'.
        /// </param>
        /// <returns>
        ///    Same shape as <c>keys</c>.  Values found in the table, or <c>default_values</c>
        ///    for missing keys.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The tensor <c>keys</c> must of the same type as the keys of the table.
        ///    The output <c>values</c> is of the type of the table values.
        ///    
        ///    The scalar <c>default_value</c> is the value output for keys not present in the
        ///    table. It must also be of the same type as the table values.
        /// </remarks>
        public static Tensor lookup_table_find_v2 (Tensor table_handle, Tensor keys, Tensor default_value, string name = "LookupTableFindV2")
        {
            var dict = new Dictionary<string, object>();
            dict["table_handle"] = table_handle;
            dict["keys"] = keys;
            dict["default_value"] = default_value;
            var op = _op_def_lib._apply_op_helper("LookupTableFindV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Replaces the contents of the table with the specified keys and values.
        /// </summary>
        /// <param name="table_handle">
        ///    Handle to the table.
        /// </param>
        /// <param name="keys">
        ///    Any shape.  Keys to look up.
        /// </param>
        /// <param name="values">
        ///    Values to associate with keys.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LookupTableImport'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    The tensor <c>keys</c> must be of the same type as the keys of the table.
        ///    The tensor <c>values</c> must be of the type of the table values.
        /// </remarks>
        public static Operation lookup_table_import (Tensor table_handle, Tensor keys, Tensor values, string name = "LookupTableImport")
        {
            var dict = new Dictionary<string, object>();
            dict["table_handle"] = table_handle;
            dict["keys"] = keys;
            dict["values"] = values;
            var op = _op_def_lib._apply_op_helper("LookupTableImport", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Replaces the contents of the table with the specified keys and values.
        /// </summary>
        /// <param name="table_handle">
        ///    Handle to the table.
        /// </param>
        /// <param name="keys">
        ///    Any shape.  Keys to look up.
        /// </param>
        /// <param name="values">
        ///    Values to associate with keys.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LookupTableImportV2'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    The tensor <c>keys</c> must be of the same type as the keys of the table.
        ///    The tensor <c>values</c> must be of the type of the table values.
        /// </remarks>
        public static Operation lookup_table_import_v2 (Tensor table_handle, Tensor keys, Tensor values, string name = "LookupTableImportV2")
        {
            var dict = new Dictionary<string, object>();
            dict["table_handle"] = table_handle;
            dict["keys"] = keys;
            dict["values"] = values;
            var op = _op_def_lib._apply_op_helper("LookupTableImportV2", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Updates the table to associates keys with values.
        /// </summary>
        /// <param name="table_handle">
        ///    Handle to the table.
        /// </param>
        /// <param name="keys">
        ///    Any shape.  Keys to look up.
        /// </param>
        /// <param name="values">
        ///    Values to associate with keys.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LookupTableInsert'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    The tensor <c>keys</c> must be of the same type as the keys of the table.
        ///    The tensor <c>values</c> must be of the type of the table values.
        /// </remarks>
        public static Operation lookup_table_insert (Tensor table_handle, Tensor keys, Tensor values, string name = "LookupTableInsert")
        {
            var dict = new Dictionary<string, object>();
            dict["table_handle"] = table_handle;
            dict["keys"] = keys;
            dict["values"] = values;
            var op = _op_def_lib._apply_op_helper("LookupTableInsert", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Updates the table to associates keys with values.
        /// </summary>
        /// <param name="table_handle">
        ///    Handle to the table.
        /// </param>
        /// <param name="keys">
        ///    Any shape.  Keys to look up.
        /// </param>
        /// <param name="values">
        ///    Values to associate with keys.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LookupTableInsertV2'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    The tensor <c>keys</c> must be of the same type as the keys of the table.
        ///    The tensor <c>values</c> must be of the type of the table values.
        /// </remarks>
        public static Operation lookup_table_insert_v2 (Tensor table_handle, Tensor keys, Tensor values, string name = "LookupTableInsertV2")
        {
            var dict = new Dictionary<string, object>();
            dict["table_handle"] = table_handle;
            dict["keys"] = keys;
            dict["values"] = values;
            var op = _op_def_lib._apply_op_helper("LookupTableInsertV2", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Computes the number of elements in the given table.
        /// </summary>
        /// <param name="table_handle">
        ///    Handle to the table.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LookupTableSize'.
        /// </param>
        /// <returns>
        ///    Scalar that contains number of elements in the table.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor lookup_table_size (Tensor table_handle, string name = "LookupTableSize")
        {
            var dict = new Dictionary<string, object>();
            dict["table_handle"] = table_handle;
            var op = _op_def_lib._apply_op_helper("LookupTableSize", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the number of elements in the given table.
        /// </summary>
        /// <param name="table_handle">
        ///    Handle to the table.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LookupTableSizeV2'.
        /// </param>
        /// <returns>
        ///    Scalar that contains number of elements in the table.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor lookup_table_size_v2 (Tensor table_handle, string name = "LookupTableSizeV2")
        {
            var dict = new Dictionary<string, object>();
            dict["table_handle"] = table_handle;
            var op = _op_def_lib._apply_op_helper("LookupTableSizeV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Forwards the input to the output.
        /// </summary>
        /// <param name="input">
        ///    A boolean scalar, representing the branch predicate of the Switch op.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'LoopCond'.
        /// </param>
        /// <returns>
        ///    The same tensor as <c>input</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operator represents the loop termination condition used by the
        ///    "pivot" switches of a loop.
        /// </remarks>
        public static Tensor loop_cond (Tensor input, string name = "LoopCond")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("LoopCond", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Makes a new iterator from the given <c>dataset</c> and stores it in <c>iterator</c>.
        /// </summary>
        /// <param name="dataset">
        /// </param>
        /// <param name="iterator">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MakeIterator'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    This operation may be executed multiple times. Each execution will reset the
        ///    iterator in <c>iterator</c> to the first element of <c>dataset</c>.
        /// </remarks>
        public static Operation make_iterator (Tensor dataset, Tensor iterator, string name = "MakeIterator")
        {
            var dict = new Dictionary<string, object>();
            dict["dataset"] = dataset;
            dict["iterator"] = iterator;
            var op = _op_def_lib._apply_op_helper("MakeIterator", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Op removes all elements in the underlying container.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MapClear'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        /// </param>
        /// <param name="capacity">
        /// </param>
        /// <param name="memory_limit">
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation map_clear (TF_DataType[] dtypes, int? capacity = null, int? memory_limit = null, string container = null, string shared_name = null, string name = "MapClear")
        {
            var dict = new Dictionary<string, object>();
            dict["dtypes"] = dtypes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (memory_limit.HasValue)
                dict["memory_limit"] = memory_limit.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("MapClear", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Op returns the number of incomplete elements in the underlying container.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MapIncompleteSize'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        /// </param>
        /// <param name="capacity">
        /// </param>
        /// <param name="memory_limit">
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor map_incomplete_size (TF_DataType[] dtypes, int? capacity = null, int? memory_limit = null, string container = null, string shared_name = null, string name = "MapIncompleteSize")
        {
            var dict = new Dictionary<string, object>();
            dict["dtypes"] = dtypes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (memory_limit.HasValue)
                dict["memory_limit"] = memory_limit.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("MapIncompleteSize", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Op peeks at the values at the specified key.  If the
        /// </summary>
        /// <param name="key">
        /// </param>
        /// <param name="indices">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MapPeek'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        /// </param>
        /// <param name="capacity">
        /// </param>
        /// <param name="memory_limit">
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    underlying container does not contain this key
        ///    this op will block until it does.
        /// </remarks>
        public static Tensor[] map_peek (Tensor key, Tensor indices, TF_DataType[] dtypes, int? capacity = null, int? memory_limit = null, string container = null, string shared_name = null, string name = "MapPeek")
        {
            var dict = new Dictionary<string, object>();
            dict["key"] = key;
            dict["indices"] = indices;
            dict["dtypes"] = dtypes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (memory_limit.HasValue)
                dict["memory_limit"] = memory_limit.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("MapPeek", name: name, keywords: dict);
            int _idx = 0;
            var values = Enumerable.Range(0, op.OutputListLength("values")).Select(_ => op.outputs[_idx++]).ToArray();
            return (values);
        }

        /// <summary>
        ///    Op returns the number of elements in the underlying container.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MapSize'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        /// </param>
        /// <param name="capacity">
        /// </param>
        /// <param name="memory_limit">
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor map_size (TF_DataType[] dtypes, int? capacity = null, int? memory_limit = null, string container = null, string shared_name = null, string name = "MapSize")
        {
            var dict = new Dictionary<string, object>();
            dict["dtypes"] = dtypes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (memory_limit.HasValue)
                dict["memory_limit"] = memory_limit.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("MapSize", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Stage (key, values) in the underlying container which behaves like a hashtable.
        /// </summary>
        /// <param name="key">
        ///    int64
        /// </param>
        /// <param name="indices">
        /// </param>
        /// <param name="values">
        ///    a list of tensors
        ///    dtypes A list of data types that inserted values should adhere to.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MapStage'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        /// </param>
        /// <param name="capacity">
        ///    Maximum number of elements in the Staging Area. If &amp;gt; 0, inserts
        ///    on the container will block when the capacity is reached.
        /// </param>
        /// <param name="memory_limit">
        /// </param>
        /// <param name="container">
        ///    If non-empty, this queue is placed in the given container. Otherwise,
        ///    a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    It is necessary to match this name to the matching Unstage Op.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation map_stage (Tensor key, Tensor indices, Tensor[] values, TF_DataType[] dtypes, int? capacity = null, int? memory_limit = null, string container = null, string shared_name = null, string name = "MapStage")
        {
            var dict = new Dictionary<string, object>();
            dict["key"] = key;
            dict["indices"] = indices;
            dict["values"] = values;
            dict["dtypes"] = dtypes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (memory_limit.HasValue)
                dict["memory_limit"] = memory_limit.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("MapStage", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Op removes and returns the values associated with the key
        /// </summary>
        /// <param name="key">
        /// </param>
        /// <param name="indices">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MapUnstage'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        /// </param>
        /// <param name="capacity">
        /// </param>
        /// <param name="memory_limit">
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    from the underlying container.   If the underlying container
        ///    does not contain this key, the op will block until it does.
        /// </remarks>
        public static Tensor[] map_unstage (Tensor key, Tensor indices, TF_DataType[] dtypes, int? capacity = null, int? memory_limit = null, string container = null, string shared_name = null, string name = "MapUnstage")
        {
            var dict = new Dictionary<string, object>();
            dict["key"] = key;
            dict["indices"] = indices;
            dict["dtypes"] = dtypes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (memory_limit.HasValue)
                dict["memory_limit"] = memory_limit.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("MapUnstage", name: name, keywords: dict);
            int _idx = 0;
            var values = Enumerable.Range(0, op.OutputListLength("values")).Select(_ => op.outputs[_idx++]).ToArray();
            return (values);
        }

        /// <summary>
        ///    Op removes and returns a random (key, value)
        /// </summary>
        /// <param name="indices">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MapUnstageNoKey'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        /// </param>
        /// <param name="capacity">
        /// </param>
        /// <param name="memory_limit">
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    key :
        ///    values :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    from the underlying container.   If the underlying container
        ///    does not contain elements, the op will block until it does.
        /// </remarks>
        public static (Tensor key, Tensor[] values) map_unstage_no_key (Tensor indices, TF_DataType[] dtypes, int? capacity = null, int? memory_limit = null, string container = null, string shared_name = null, string name = "MapUnstageNoKey")
        {
            var dict = new Dictionary<string, object>();
            dict["indices"] = indices;
            dict["dtypes"] = dtypes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (memory_limit.HasValue)
                dict["memory_limit"] = memory_limit.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("MapUnstageNoKey", name: name, keywords: dict);
            int _idx = 0;
            var key = op.outputs[_idx++];
            var values = Enumerable.Range(0, op.OutputListLength("values")).Select(_ => op.outputs[_idx++]).ToArray();
            return (key, values);
        }

        /// <summary>
        ///    Multiply the matrix "a" by the matrix "b".
        /// </summary>
        /// <param name="a">
        /// </param>
        /// <param name="b">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MatMul'.
        /// </param>
        /// <param name="transpose_a">
        ///    If true, "a" is transposed before multiplication.
        /// </param>
        /// <param name="transpose_b">
        ///    If true, "b" is transposed before multiplication.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The inputs must be two-dimensional matrices and the inner dimension of
        ///    "a" (after being transposed if transpose_a is true) must match the
        ///    outer dimension of "b" (after being transposed if transposed_b is
        ///    true).
        ///    
        ///    *Note*: The default kernel implementation for MatMul on GPUs uses
        ///    cublas.
        /// </remarks>
        public static Tensor mat_mul (Tensor a, Tensor b, bool? transpose_a = null, bool? transpose_b = null, string name = "MatMul")
        {
            var dict = new Dictionary<string, object>();
            dict["a"] = a;
            dict["b"] = b;
            if (transpose_a.HasValue)
                dict["transpose_a"] = transpose_a.Value;
            if (transpose_b.HasValue)
                dict["transpose_b"] = transpose_b.Value;
            var op = _op_def_lib._apply_op_helper("MatMul", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the set of files matching one or more glob patterns.
        /// </summary>
        /// <param name="pattern">
        ///    Shell wildcard pattern(s). Scalar or vector of type string.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MatchingFiles'.
        /// </param>
        /// <returns>
        ///    A vector of matching filenames.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Note that this routine only supports wildcard characters in the
        ///    basename portion of the pattern, not in the directory portion.
        ///    Note also that the order of filenames returned can be non-deterministic.
        /// </remarks>
        public static Tensor matching_files (Tensor pattern, string name = "MatchingFiles")
        {
            var dict = new Dictionary<string, object>();
            dict["pattern"] = pattern;
            var op = _op_def_lib._apply_op_helper("MatchingFiles", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Copy a tensor setting everything outside a central band in each innermost matrix
        /// </summary>
        /// <param name="input">
        ///    Rank <c>k</c> tensor.
        /// </param>
        /// <param name="num_lower">
        ///    0-D tensor. Number of subdiagonals to keep. If negative, keep entire
        ///    lower triangle.
        /// </param>
        /// <param name="num_upper">
        ///    0-D tensor. Number of superdiagonals to keep. If negative, keep
        ///    entire upper triangle.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MatrixBandPart'.
        /// </param>
        /// <returns>
        ///    Rank <c>k</c> tensor of the same shape as input. The extracted banded tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    to zero.
        ///    
        ///    The <c>band</c> part is computed as follows:
        ///    Assume <c>input</c> has <c>k</c> dimensions <c>[I, J, K, ..., M, N]</c>, then the output is a
        ///    tensor with the same shape where
        ///    
        ///    <c>band[i, j, k, ..., m, n] = in_band(m, n) * input[i, j, k, ..., m, n]</c>.
        ///    
        ///    The indicator function
        ///    
        ///    <c>in_band(m, n) = (num_lower &amp;lt; 0 || (m-n) &amp;lt;= num_lower)) &amp;&amp;
        ///    (num_upper &amp;lt; 0 || (n-m) &amp;lt;= num_upper)</c>.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # if 'input' is [[ 0,  1,  2, 3]
        ///    [-1,  0,  1, 2]
        ///    [-2, -1,  0, 1]
        ///    [-3, -2, -1, 0]],
        ///    
        ///    tf.matrix_band_part(input, 1, -1) ==&amp;gt; [[ 0,  1,  2, 3]
        ///    [-1,  0,  1, 2]
        ///    [ 0, -1,  0, 1]
        ///    [ 0,  0, -1, 0]],
        ///    
        ///    tf.matrix_band_part(input, 2, 1) ==&amp;gt; [[ 0,  1,  0, 0]
        ///    [-1,  0,  1, 0]
        ///    [-2, -1,  0, 1]
        ///    [ 0, -2, -1, 0]]
        ///   </code>
        ///    
        ///    Useful special cases:
        ///    
        ///   <code>
        ///    tf.matrix_band_part(input, 0, -1) ==&amp;gt; Upper triangular part.
        ///    tf.matrix_band_part(input, -1, 0) ==&amp;gt; Lower triangular part.
        ///    tf.matrix_band_part(input, 0, 0) ==&amp;gt; Diagonal.
        ///   </code>
        /// </remarks>
        public static Tensor matrix_band_part (Tensor input, Tensor num_lower, Tensor num_upper, string name = "MatrixBandPart")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["num_lower"] = num_lower;
            dict["num_upper"] = num_upper;
            var op = _op_def_lib._apply_op_helper("MatrixBandPart", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the determinant of one or more square matrices.
        /// </summary>
        /// <param name="input">
        ///    Shape is <c>[..., M, M]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MatrixDeterminant'.
        /// </param>
        /// <returns>
        ///    Shape is <c>[...]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The input is a tensor of shape <c>[..., M, M]</c> whose inner-most 2 dimensions
        ///    form square matrices. The output is a tensor containing the determinants
        ///    for all input submatrices <c>[..., :, :]</c>.
        /// </remarks>
        public static Tensor matrix_determinant (Tensor input, string name = "MatrixDeterminant")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("MatrixDeterminant", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns a batched diagonal tensor with a given batched diagonal values.
        /// </summary>
        /// <param name="diagonal">
        ///    Rank <c>k</c>, where <c>k &amp;gt;= 1</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MatrixDiag'.
        /// </param>
        /// <returns>
        ///    Rank <c>k+1</c>, with <c>output.shape = diagonal.shape + [diagonal.shape[-1]]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given a <c>diagonal</c>, this operation returns a tensor with the <c>diagonal</c> and
        ///    everything else padded with zeros. The diagonal is computed as follows:
        ///    
        ///    Assume <c>diagonal</c> has <c>k</c> dimensions <c>[I, J, K, ..., N]</c>, then the output is a
        ///    tensor of rank <c>k+1</c> with dimensions [I, J, K, ..., N, N]<c> where:
        ///    
        ///    </c>output[i, j, k, ..., m, n] = 1{m=n} * diagonal[i, j, k, ..., n]<c>.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # 'diagonal' is [[1, 2, 3, 4], [5, 6, 7, 8]]
        ///    
        ///    and diagonal.shape = (2, 4)
        ///    
        ///    tf.matrix_diag(diagonal) ==&amp;gt; [[[1, 0, 0, 0]
        ///    [0, 2, 0, 0]
        ///    [0, 0, 3, 0]
        ///    [0, 0, 0, 4]],
        ///    [[5, 0, 0, 0]
        ///    [0, 6, 0, 0]
        ///    [0, 0, 7, 0]
        ///    [0, 0, 0, 8]]]
        ///    
        ///    which has shape (2, 4, 4)
        ///   </code>
        /// </remarks>
        public static Tensor matrix_diag (Tensor diagonal, string name = "MatrixDiag")
        {
            var dict = new Dictionary<string, object>();
            dict["diagonal"] = diagonal;
            var op = _op_def_lib._apply_op_helper("MatrixDiag", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the batched diagonal part of a batched tensor.
        /// </summary>
        /// <param name="input">
        ///    Rank <c>k</c> tensor where <c>k &amp;gt;= 2</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MatrixDiagPart'.
        /// </param>
        /// <returns>
        ///    The extracted diagonal(s) having shape
        ///    <c>diagonal.shape = input.shape[:-2] + [min(input.shape[-2:])]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation returns a tensor with the <c>diagonal</c> part
        ///    of the batched <c>input</c>. The <c>diagonal</c> part is computed as follows:
        ///    
        ///    Assume <c>input</c> has <c>k</c> dimensions <c>[I, J, K, ..., M, N]</c>, then the output is a
        ///    tensor of rank <c>k - 1</c> with dimensions <c>[I, J, K, ..., min(M, N)]</c> where:
        ///    
        ///    <c>diagonal[i, j, k, ..., n] = input[i, j, k, ..., n, n]</c>.
        ///    
        ///    The input must be at least a matrix.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # 'input' is [[[1, 0, 0, 0]
        ///    [0, 2, 0, 0]
        ///    [0, 0, 3, 0]
        ///    [0, 0, 0, 4]],
        ///    [[5, 0, 0, 0]
        ///    [0, 6, 0, 0]
        ///    [0, 0, 7, 0]
        ///    [0, 0, 0, 8]]]
        ///    
        ///    and input.shape = (2, 4, 4)
        ///    
        ///    tf.matrix_diag_part(input) ==&amp;gt; [[1, 2, 3, 4], [5, 6, 7, 8]]
        ///    
        ///    which has shape (2, 4)
        ///   </code>
        /// </remarks>
        public static Tensor matrix_diag_part (Tensor input, string name = "MatrixDiagPart")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("MatrixDiagPart", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Deprecated, use python implementation tf.linalg.matrix_exponential.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MatrixExponential'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor matrix_exponential (Tensor input, string name = "MatrixExponential")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("MatrixExponential", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the inverse of one or more square invertible matrices or their
        /// </summary>
        /// <param name="input">
        ///    Shape is <c>[..., M, M]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MatrixInverse'.
        /// </param>
        /// <param name="adjoint">
        /// </param>
        /// <returns>
        ///    Shape is <c>[..., M, M]</c>.
        ///    
        ///    @compatibility(numpy)
        ///    Equivalent to np.linalg.inv
        ///    @end_compatibility
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    adjoints (conjugate transposes).
        ///    
        ///    The input is a tensor of shape <c>[..., M, M]</c> whose inner-most 2 dimensions
        ///    form square matrices. The output is a tensor of the same shape as the input
        ///    containing the inverse for all input submatrices <c>[..., :, :]</c>.
        ///    
        ///    The op uses LU decomposition with partial pivoting to compute the inverses.
        ///    
        ///    If a matrix is not invertible there is no guarantee what the op does. It
        ///    may detect the condition and raise an exception or it may simply return a
        ///    garbage result.
        /// </remarks>
        public static Tensor matrix_inverse (Tensor input, bool? adjoint = null, string name = "MatrixInverse")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (adjoint.HasValue)
                dict["adjoint"] = adjoint.Value;
            var op = _op_def_lib._apply_op_helper("MatrixInverse", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the matrix logarithm of one or more square matrices:
        /// </summary>
        /// <param name="input">
        ///    Shape is <c>[..., M, M]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MatrixLogarithm'.
        /// </param>
        /// <returns>
        ///    Shape is <c>[..., M, M]</c>.
        ///    
        ///    @compatibility(scipy)
        ///    Equivalent to scipy.linalg.logm
        ///    @end_compatibility
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    
        ///    \\(log(exp(A)) = A\\)
        ///    
        ///    This op is only defined for complex matrices. If A is positive-definite and
        ///    real, then casting to a complex matrix, taking the logarithm and casting back
        ///    to a real matrix will give the correct result.
        ///    
        ///    This function computes the matrix logarithm using the Schur-Parlett algorithm.
        ///    Details of the algorithm can be found in Section 11.6.2 of:
        ///    Nicholas J. Higham, Functions of Matrices: Theory and Computation, SIAM 2008.
        ///    ISBN 978-0-898716-46-7.
        ///    
        ///    The input is a tensor of shape <c>[..., M, M]</c> whose inner-most 2 dimensions
        ///    form square matrices. The output is a tensor of the same shape as the input
        ///    containing the exponential for all input submatrices <c>[..., :, :]</c>.
        /// </remarks>
        public static Tensor matrix_logarithm (Tensor input, string name = "MatrixLogarithm")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("MatrixLogarithm", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns a batched matrix tensor with new batched diagonal values.
        /// </summary>
        /// <param name="input">
        ///    Rank <c>k+1</c>, where <c>k &amp;gt;= 1</c>.
        /// </param>
        /// <param name="diagonal">
        ///    Rank <c>k</c>, where <c>k &amp;gt;= 1</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MatrixSetDiag'.
        /// </param>
        /// <returns>
        ///    Rank <c>k+1</c>, with <c>output.shape = input.shape</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given <c>input</c> and <c>diagonal</c>, this operation returns a tensor with the
        ///    same shape and values as <c>input</c>, except for the main diagonal of the
        ///    innermost matrices.  These will be overwritten by the values in <c>diagonal</c>.
        ///    
        ///    The output is computed as follows:
        ///    
        ///    Assume <c>input</c> has <c>k+1</c> dimensions <c>[I, J, K, ..., M, N]</c> and <c>diagonal</c> has
        ///    <c>k</c> dimensions <c>[I, J, K, ..., min(M, N)]</c>.  Then the output is a
        ///    tensor of rank <c>k+1</c> with dimensions <c>[I, J, K, ..., M, N]</c> where:
        ///    
        ///    * <c>output[i, j, k, ..., m, n] = diagonal[i, j, k, ..., n]</c> for <c>m == n</c>.
        ///    * <c>output[i, j, k, ..., m, n] = input[i, j, k, ..., m, n]</c> for <c>m != n</c>.
        /// </remarks>
        public static Tensor matrix_set_diag (Tensor input, Tensor diagonal, string name = "MatrixSetDiag")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["diagonal"] = diagonal;
            var op = _op_def_lib._apply_op_helper("MatrixSetDiag", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Solves systems of linear equations.
        /// </summary>
        /// <param name="matrix">
        ///    Shape is <c>[..., M, M]</c>.
        /// </param>
        /// <param name="rhs">
        ///    Shape is <c>[..., M, K]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MatrixSolve'.
        /// </param>
        /// <param name="adjoint">
        ///    Boolean indicating whether to solve with <c>matrix</c> or its (block-wise)
        ///    adjoint.
        /// </param>
        /// <returns>
        ///    Shape is <c>[..., M, K]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    <c>Matrix</c> is a tensor of shape <c>[..., M, M]</c> whose inner-most 2 dimensions
        ///    form square matrices. <c>Rhs</c> is a tensor of shape <c>[..., M, K]</c>. The <c>output</c> is
        ///    a tensor shape <c>[..., M, K]</c>.  If <c>adjoint</c> is <c>False</c> then each output matrix
        ///    satisfies <c>matrix[..., :, :] * output[..., :, :] = rhs[..., :, :]</c>.
        ///    If <c>adjoint</c> is <c>True</c> then each output matrix satisfies
        ///    <c>adjoint(matrix[..., :, :]) * output[..., :, :] = rhs[..., :, :]</c>.
        /// </remarks>
        public static Tensor matrix_solve (Tensor matrix, Tensor rhs, bool? adjoint = null, string name = "MatrixSolve")
        {
            var dict = new Dictionary<string, object>();
            dict["matrix"] = matrix;
            dict["rhs"] = rhs;
            if (adjoint.HasValue)
                dict["adjoint"] = adjoint.Value;
            var op = _op_def_lib._apply_op_helper("MatrixSolve", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Solves one or more linear least-squares problems.
        /// </summary>
        /// <param name="matrix">
        ///    Shape is <c>[..., M, N]</c>.
        /// </param>
        /// <param name="rhs">
        ///    Shape is <c>[..., M, K]</c>.
        /// </param>
        /// <param name="l2_regularizer">
        ///    Scalar tensor.
        ///    
        ///    @compatibility(numpy)
        ///    Equivalent to np.linalg.lstsq
        ///    @end_compatibility
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MatrixSolveLs'.
        /// </param>
        /// <param name="fast">
        /// </param>
        /// <returns>
        ///    Shape is <c>[..., N, K]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    <c>matrix</c> is a tensor of shape <c>[..., M, N]</c> whose inner-most 2 dimensions
        ///    form real or complex matrices of size <c>[M, N]</c>. <c>Rhs</c> is a tensor of the same
        ///    type as <c>matrix</c> and shape <c>[..., M, K]</c>.
        ///    The output is a tensor shape <c>[..., N, K]</c> where each output matrix solves
        ///    each of the equations
        ///    <c>matrix[..., :, :]</c> * <c>output[..., :, :]</c> = <c>rhs[..., :, :]</c>
        ///    in the least squares sense.
        ///    
        ///    We use the following notation for (complex) matrix and right-hand sides
        ///    in the batch:
        ///    
        ///    <c>matrix</c>=\\(A \in \mathbb{C}^{m \times n}\\),
        ///    <c>rhs</c>=\\(B  \in \mathbb{C}^{m \times k}\\),
        ///    <c>output</c>=\\(X  \in \mathbb{C}^{n \times k}\\),
        ///    <c>l2_regularizer</c>=\\(\lambda \in \mathbb{R}\\).
        ///    
        ///    If <c>fast</c> is <c>True</c>, then the solution is computed by solving the normal
        ///    equations using Cholesky decomposition. Specifically, if \\(m \ge n\\) then
        ///    \\(X = (A^H A + \lambda I)^{-1} A^H B\\), which solves the least-squares
        ///    problem \\(X = \mathrm{argmin}_{Z \in \Re^{n \times k} } ||A Z - B||_F^2 + \lambda ||Z||_F^2\\).
        ///    If \\(m \lt n\\) then <c>output</c> is computed as
        ///    \\(X = A^H (A A^H + \lambda I)^{-1} B\\), which (for \\(\lambda = 0\\)) is the
        ///    minimum-norm solution to the under-determined linear system, i.e.
        ///    \\(X = \mathrm{argmin}_{Z \in \mathbb{C}^{n \times k} } ||Z||_F^2 \\),
        ///    subject to \\(A Z = B\\). Notice that the fast path is only numerically stable
        ///    when \\(A\\) is numerically full rank and has a condition number
        ///    \\(\mathrm{cond}(A) \lt \frac{1}{\sqrt{\epsilon_{mach} } }\\) or \\(\lambda\\) is
        ///    sufficiently large.
        ///    
        ///    If <c>fast</c> is <c>False</c> an algorithm based on the numerically robust complete
        ///    orthogonal decomposition is used. This computes the minimum-norm
        ///    least-squares solution, even when \\(A\\) is rank deficient. This path is
        ///    typically 6-7 times slower than the fast path. If <c>fast</c> is <c>False</c> then
        ///    <c>l2_regularizer</c> is ignored.
        /// </remarks>
        public static Tensor matrix_solve_ls (Tensor matrix, Tensor rhs, Tensor l2_regularizer, bool? fast = null, string name = "MatrixSolveLs")
        {
            var dict = new Dictionary<string, object>();
            dict["matrix"] = matrix;
            dict["rhs"] = rhs;
            dict["l2_regularizer"] = l2_regularizer;
            if (fast.HasValue)
                dict["fast"] = fast.Value;
            var op = _op_def_lib._apply_op_helper("MatrixSolveLs", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Solves systems of linear equations with upper or lower triangular matrices by
        /// </summary>
        /// <param name="matrix">
        ///    Shape is <c>[..., M, M]</c>.
        /// </param>
        /// <param name="rhs">
        ///    Shape is <c>[..., M, K]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MatrixTriangularSolve'.
        /// </param>
        /// <param name="lower">
        ///    Boolean indicating whether the innermost matrices in <c>matrix</c> are
        ///    lower or upper triangular.
        /// </param>
        /// <param name="adjoint">
        ///    Boolean indicating whether to solve with <c>matrix</c> or its (block-wise)
        ///    adjoint.
        ///    
        ///    @compatibility(numpy)
        ///    Equivalent to scipy.linalg.solve_triangular
        ///    @end_compatibility
        /// </param>
        /// <returns>
        ///    Shape is <c>[..., M, K]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    backsubstitution.
        ///    
        ///    <c>matrix</c> is a tensor of shape <c>[..., M, M]</c> whose inner-most 2 dimensions form
        ///    square matrices. If <c>lower</c> is <c>True</c> then the strictly upper triangular part
        ///    of each inner-most matrix is assumed to be zero and not accessed.
        ///    If <c>lower</c> is False then the strictly lower triangular part of each inner-most
        ///    matrix is assumed to be zero and not accessed.
        ///    <c>rhs</c> is a tensor of shape <c>[..., M, K]</c>.
        ///    
        ///    The output is a tensor of shape <c>[..., M, K]</c>. If <c>adjoint</c> is
        ///    <c>True</c> then the innermost matrices in <c>output</c> satisfy matrix equations
        ///    <c>matrix[..., :, :] * output[..., :, :] = rhs[..., :, :]</c>.
        ///    If <c>adjoint</c> is <c>False</c> then the strictly then the  innermost matrices in
        ///    <c>output</c> satisfy matrix equations
        ///    <c>adjoint(matrix[..., i, k]) * output[..., k, j] = rhs[..., i, j]</c>.
        /// </remarks>
        public static Tensor matrix_triangular_solve (Tensor matrix, Tensor rhs, bool? lower = null, bool? adjoint = null, string name = "MatrixTriangularSolve")
        {
            var dict = new Dictionary<string, object>();
            dict["matrix"] = matrix;
            dict["rhs"] = rhs;
            if (lower.HasValue)
                dict["lower"] = lower.Value;
            if (adjoint.HasValue)
                dict["adjoint"] = adjoint.Value;
            var op = _op_def_lib._apply_op_helper("MatrixTriangularSolve", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the maximum of elements across dimensions of a tensor.
        /// </summary>
        /// <param name="input">
        ///    The tensor to reduce.
        /// </param>
        /// <param name="reduction_indices">
        ///    The dimensions to reduce. Must be in the range
        ///    <c>[-rank(input), rank(input))</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Max'.
        /// </param>
        /// <param name="keep_dims">
        ///    If true, retain reduced dimensions with length 1.
        /// </param>
        /// <returns>
        ///    The reduced tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Reduces <c>input</c> along the dimensions given in <c>axis</c>. Unless
        ///    <c>keep_dims</c> is true, the rank of the tensor is reduced by 1 for each entry in
        ///    <c>axis</c>. If <c>keep_dims</c> is true, the reduced dimensions are
        ///    retained with length 1.
        /// </remarks>
        public static Tensor max (Tensor input, Tensor reduction_indices, bool? keep_dims = null, string name = "Max")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["reduction_indices"] = reduction_indices;
            if (keep_dims.HasValue)
                dict["keep_dims"] = keep_dims.Value;
            var op = _op_def_lib._apply_op_helper("Max", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Performs max pooling on the input.
        /// </summary>
        /// <param name="input">
        ///    4-D input to pool over.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MaxPool'.
        /// </param>
        /// <param name="ksize">
        ///    Optional argument
        ///    The size of the window for each dimension of the input tensor.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    The stride of the sliding window for each dimension of the
        ///    input tensor.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="data_format">
        ///    Specify the data format of the input and output data. With the
        ///    default format "NHWC", the data is stored in the order of:
        ///    [batch, in_height, in_width, in_channels].
        ///    Alternatively, the format could be "NCHW", the data storage order of:
        ///    [batch, in_channels, in_height, in_width].
        /// </param>
        /// <returns>
        ///    The max pooled output tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor max_pool (Tensor input, int[] ksize, int[] strides, string padding, string data_format = null, string name = "MaxPool")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["ksize"] = ksize;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (data_format != null)
                dict["data_format"] = data_format;
            var op = _op_def_lib._apply_op_helper("MaxPool", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Performs 3D max pooling on the input.
        /// </summary>
        /// <param name="input">
        ///    Shape <c>[batch, depth, rows, cols, channels]</c> tensor to pool over.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MaxPool3D'.
        /// </param>
        /// <param name="ksize">
        ///    Optional argument
        ///    1-D tensor of length 5. The size of the window for each dimension of
        ///    the input tensor. Must have <c>ksize[0] = ksize[4] = 1</c>.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    1-D tensor of length 5. The stride of the sliding window for each
        ///    dimension of <c>input</c>. Must have <c>strides[0] = strides[4] = 1</c>.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="data_format">
        ///    The data format of the input and output data. With the
        ///    default format "NDHWC", the data is stored in the order of:
        ///    [batch, in_depth, in_height, in_width, in_channels].
        ///    Alternatively, the format could be "NCDHW", the data storage order is:
        ///    [batch, in_channels, in_depth, in_height, in_width].
        /// </param>
        /// <returns>
        ///    The max pooled output tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor max_pool3d (Tensor input, int[] ksize, int[] strides, string padding, string data_format = null, string name = "MaxPool3D")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["ksize"] = ksize;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (data_format != null)
                dict["data_format"] = data_format;
            var op = _op_def_lib._apply_op_helper("MaxPool3D", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes gradients of max pooling function.
        /// </summary>
        /// <param name="orig_input">
        ///    The original input tensor.
        /// </param>
        /// <param name="orig_output">
        ///    The original output tensor.
        /// </param>
        /// <param name="grad">
        ///    Output backprop of shape <c>[batch, depth, rows, cols, channels]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MaxPool3DGrad'.
        /// </param>
        /// <param name="ksize">
        ///    Optional argument
        ///    1-D tensor of length 5. The size of the window for each dimension of
        ///    the input tensor. Must have <c>ksize[0] = ksize[4] = 1</c>.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    1-D tensor of length 5. The stride of the sliding window for each
        ///    dimension of <c>input</c>. Must have <c>strides[0] = strides[4] = 1</c>.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="data_format">
        ///    The data format of the input and output data. With the
        ///    default format "NDHWC", the data is stored in the order of:
        ///    [batch, in_depth, in_height, in_width, in_channels].
        ///    Alternatively, the format could be "NCDHW", the data storage order is:
        ///    [batch, in_channels, in_depth, in_height, in_width].
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor max_pool3d_grad (Tensor orig_input, Tensor orig_output, Tensor grad, int[] ksize, int[] strides, string padding, string data_format = null, string name = "MaxPool3DGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["orig_input"] = orig_input;
            dict["orig_output"] = orig_output;
            dict["grad"] = grad;
            dict["ksize"] = ksize;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (data_format != null)
                dict["data_format"] = data_format;
            var op = _op_def_lib._apply_op_helper("MaxPool3DGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes second-order gradients of the maxpooling function.
        /// </summary>
        /// <param name="orig_input">
        ///    The original input tensor.
        /// </param>
        /// <param name="orig_output">
        ///    The original output tensor.
        /// </param>
        /// <param name="grad">
        ///    Output backprop of shape <c>[batch, depth, rows, cols, channels]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MaxPool3DGradGrad'.
        /// </param>
        /// <param name="ksize">
        ///    Optional argument
        ///    1-D tensor of length 5. The size of the window for each dimension of
        ///    the input tensor. Must have <c>ksize[0] = ksize[4] = 1</c>.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    1-D tensor of length 5. The stride of the sliding window for each
        ///    dimension of <c>input</c>. Must have <c>strides[0] = strides[4] = 1</c>.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="data_format">
        ///    The data format of the input and output data. With the
        ///    default format "NDHWC", the data is stored in the order of:
        ///    [batch, in_depth, in_height, in_width, in_channels].
        ///    Alternatively, the format could be "NCDHW", the data storage order is:
        ///    [batch, in_channels, in_depth, in_height, in_width].
        /// </param>
        /// <returns>
        ///    Gradients of gradients w.r.t. the input to <c>max_pool</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor max_pool3d_grad_grad (Tensor orig_input, Tensor orig_output, Tensor grad, int[] ksize, int[] strides, string padding, string data_format = null, string name = "MaxPool3DGradGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["orig_input"] = orig_input;
            dict["orig_output"] = orig_output;
            dict["grad"] = grad;
            dict["ksize"] = ksize;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (data_format != null)
                dict["data_format"] = data_format;
            var op = _op_def_lib._apply_op_helper("MaxPool3DGradGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes gradients of the maxpooling function.
        /// </summary>
        /// <param name="orig_input">
        ///    The original input tensor.
        /// </param>
        /// <param name="orig_output">
        ///    The original output tensor.
        /// </param>
        /// <param name="grad">
        ///    4-D.  Gradients w.r.t. the output of <c>max_pool</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MaxPoolGrad'.
        /// </param>
        /// <param name="ksize">
        ///    Optional argument
        ///    The size of the window for each dimension of the input tensor.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    The stride of the sliding window for each dimension of the
        ///    input tensor.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="data_format">
        ///    Specify the data format of the input and output data. With the
        ///    default format "NHWC", the data is stored in the order of:
        ///    [batch, in_height, in_width, in_channels].
        ///    Alternatively, the format could be "NCHW", the data storage order of:
        ///    [batch, in_channels, in_height, in_width].
        /// </param>
        /// <returns>
        ///    Gradients w.r.t. the input to <c>max_pool</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor max_pool_grad (Tensor orig_input, Tensor orig_output, Tensor grad, int[] ksize, int[] strides, string padding, string data_format = null, string name = "MaxPoolGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["orig_input"] = orig_input;
            dict["orig_output"] = orig_output;
            dict["grad"] = grad;
            dict["ksize"] = ksize;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (data_format != null)
                dict["data_format"] = data_format;
            var op = _op_def_lib._apply_op_helper("MaxPoolGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes second-order gradients of the maxpooling function.
        /// </summary>
        /// <param name="orig_input">
        ///    The original input tensor.
        /// </param>
        /// <param name="orig_output">
        ///    The original output tensor.
        /// </param>
        /// <param name="grad">
        ///    4-D.  Gradients of gradients w.r.t. the input of <c>max_pool</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MaxPoolGradGrad'.
        /// </param>
        /// <param name="ksize">
        ///    Optional argument
        ///    The size of the window for each dimension of the input tensor.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    The stride of the sliding window for each dimension of the
        ///    input tensor.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="data_format">
        ///    Specify the data format of the input and output data. With the
        ///    default format "NHWC", the data is stored in the order of:
        ///    [batch, in_height, in_width, in_channels].
        ///    Alternatively, the format could be "NCHW", the data storage order of:
        ///    [batch, in_channels, in_height, in_width].
        /// </param>
        /// <returns>
        ///    Gradients of gradients w.r.t. the input to <c>max_pool</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor max_pool_grad_grad (Tensor orig_input, Tensor orig_output, Tensor grad, int[] ksize, int[] strides, string padding, string data_format = null, string name = "MaxPoolGradGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["orig_input"] = orig_input;
            dict["orig_output"] = orig_output;
            dict["grad"] = grad;
            dict["ksize"] = ksize;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (data_format != null)
                dict["data_format"] = data_format;
            var op = _op_def_lib._apply_op_helper("MaxPoolGradGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes second-order gradients of the maxpooling function.
        /// </summary>
        /// <param name="orig_input">
        ///    The original input tensor.
        /// </param>
        /// <param name="orig_output">
        ///    The original output tensor.
        /// </param>
        /// <param name="grad">
        ///    4-D.  Gradients of gradients w.r.t. the input of <c>max_pool</c>.
        /// </param>
        /// <param name="ksize">
        ///    The size of the window for each dimension of the input tensor.
        /// </param>
        /// <param name="strides">
        ///    The stride of the sliding window for each dimension of the
        ///    input tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MaxPoolGradGradV2'.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="data_format">
        ///    Specify the data format of the input and output data. With the
        ///    default format "NHWC", the data is stored in the order of:
        ///    [batch, in_height, in_width, in_channels].
        ///    Alternatively, the format could be "NCHW", the data storage order of:
        ///    [batch, in_channels, in_height, in_width].
        /// </param>
        /// <returns>
        ///    Gradients of gradients w.r.t. the input to <c>max_pool</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor max_pool_grad_grad_v2 (Tensor orig_input, Tensor orig_output, Tensor grad, Tensor ksize, Tensor strides, string padding, string data_format = null, string name = "MaxPoolGradGradV2")
        {
            var dict = new Dictionary<string, object>();
            dict["orig_input"] = orig_input;
            dict["orig_output"] = orig_output;
            dict["grad"] = grad;
            dict["ksize"] = ksize;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (data_format != null)
                dict["data_format"] = data_format;
            var op = _op_def_lib._apply_op_helper("MaxPoolGradGradV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes second-order gradients of the maxpooling function.
        /// </summary>
        /// <param name="input">
        ///    The original input.
        /// </param>
        /// <param name="grad">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.  Gradients w.r.t. the
        ///    input of <c>max_pool</c>.
        /// </param>
        /// <param name="argmax">
        ///    The indices of the maximum values chosen for each output of <c>max_pool</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MaxPoolGradGradWithArgmax'.
        /// </param>
        /// <param name="ksize">
        ///    Optional argument
        ///    The size of the window for each dimension of the input tensor.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    The stride of the sliding window for each dimension of the
        ///    input tensor.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <returns>
        ///    Gradients of gradients w.r.t. the input of <c>max_pool</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor max_pool_grad_grad_with_argmax (Tensor input, Tensor grad, Tensor argmax, int[] ksize, int[] strides, string padding, string name = "MaxPoolGradGradWithArgmax")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["grad"] = grad;
            dict["argmax"] = argmax;
            dict["ksize"] = ksize;
            dict["strides"] = strides;
            dict["padding"] = padding;
            var op = _op_def_lib._apply_op_helper("MaxPoolGradGradWithArgmax", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes gradients of the maxpooling function.
        /// </summary>
        /// <param name="orig_input">
        ///    The original input tensor.
        /// </param>
        /// <param name="orig_output">
        ///    The original output tensor.
        /// </param>
        /// <param name="grad">
        ///    4-D.  Gradients w.r.t. the output of <c>max_pool</c>.
        /// </param>
        /// <param name="ksize">
        ///    The size of the window for each dimension of the input tensor.
        /// </param>
        /// <param name="strides">
        ///    The stride of the sliding window for each dimension of the
        ///    input tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MaxPoolGradV2'.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="data_format">
        ///    Specify the data format of the input and output data. With the
        ///    default format "NHWC", the data is stored in the order of:
        ///    [batch, in_height, in_width, in_channels].
        ///    Alternatively, the format could be "NCHW", the data storage order of:
        ///    [batch, in_channels, in_height, in_width].
        /// </param>
        /// <returns>
        ///    Gradients w.r.t. the input to <c>max_pool</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor max_pool_grad_v2 (Tensor orig_input, Tensor orig_output, Tensor grad, Tensor ksize, Tensor strides, string padding, string data_format = null, string name = "MaxPoolGradV2")
        {
            var dict = new Dictionary<string, object>();
            dict["orig_input"] = orig_input;
            dict["orig_output"] = orig_output;
            dict["grad"] = grad;
            dict["ksize"] = ksize;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (data_format != null)
                dict["data_format"] = data_format;
            var op = _op_def_lib._apply_op_helper("MaxPoolGradV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes gradients of the maxpooling function.
        /// </summary>
        /// <param name="input">
        ///    The original input.
        /// </param>
        /// <param name="grad">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.  Gradients w.r.t. the
        ///    output of <c>max_pool</c>.
        /// </param>
        /// <param name="argmax">
        ///    The indices of the maximum values chosen for each output of <c>max_pool</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MaxPoolGradWithArgmax'.
        /// </param>
        /// <param name="ksize">
        ///    Optional argument
        ///    The size of the window for each dimension of the input tensor.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    The stride of the sliding window for each dimension of the
        ///    input tensor.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <returns>
        ///    Gradients w.r.t. the input of <c>max_pool</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor max_pool_grad_with_argmax (Tensor input, Tensor grad, Tensor argmax, int[] ksize, int[] strides, string padding, string name = "MaxPoolGradWithArgmax")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["grad"] = grad;
            dict["argmax"] = argmax;
            dict["ksize"] = ksize;
            dict["strides"] = strides;
            dict["padding"] = padding;
            var op = _op_def_lib._apply_op_helper("MaxPoolGradWithArgmax", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Performs max pooling on the input.
        /// </summary>
        /// <param name="input">
        ///    4-D input to pool over.
        /// </param>
        /// <param name="ksize">
        ///    The size of the window for each dimension of the input tensor.
        /// </param>
        /// <param name="strides">
        ///    The stride of the sliding window for each dimension of the
        ///    input tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MaxPoolV2'.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="data_format">
        ///    Specify the data format of the input and output data. With the
        ///    default format "NHWC", the data is stored in the order of:
        ///    [batch, in_height, in_width, in_channels].
        ///    Alternatively, the format could be "NCHW", the data storage order of:
        ///    [batch, in_channels, in_height, in_width].
        /// </param>
        /// <returns>
        ///    The max pooled output tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor max_pool_v2 (Tensor input, Tensor ksize, Tensor strides, string padding, string data_format = null, string name = "MaxPoolV2")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["ksize"] = ksize;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (data_format != null)
                dict["data_format"] = data_format;
            var op = _op_def_lib._apply_op_helper("MaxPoolV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Performs max pooling on the input and outputs both max values and indices.
        /// </summary>
        /// <param name="input">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.  Input to pool over.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MaxPoolWithArgmax'.
        /// </param>
        /// <param name="ksize">
        ///    Optional argument
        ///    The size of the window for each dimension of the input tensor.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    The stride of the sliding window for each dimension of the
        ///    input tensor.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="Targmax">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output : The max pooled output tensor.
        ///    argmax : 4-D.  The flattened indices of the max values chosen for each output.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    The indices in <c>argmax</c> are flattened, so that a maximum value at position
        ///    <c>[b, y, x, c]</c> becomes flattened index
        ///    <c>((b * height + y) * width + x) * channels + c</c>.
        ///    
        ///    The indices returned are always in <c>[0, height) x [0, width)</c> before flattening,
        ///    even if padding is involved and the mathematically correct answer is outside
        ///    (either negative or too large).  This is a bug, but fixing it is difficult to do
        ///    in a safe backwards compatible way, especially due to flattening.
        /// </remarks>
        public static (Tensor output, Tensor argmax) max_pool_with_argmax (Tensor input, int[] ksize, int[] strides, string padding, TF_DataType? Targmax = null, string name = "MaxPoolWithArgmax")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["ksize"] = ksize;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (Targmax.HasValue)
                dict["Targmax"] = Targmax.Value;
            var op = _op_def_lib._apply_op_helper("MaxPoolWithArgmax", name: name, keywords: dict);
            int _idx = 0;
            var output = op.outputs[_idx++];
            var argmax = op.outputs[_idx++];
            return (output, argmax);
        }

        /// <summary>
        ///    Returns the max of x and y (i.e. x &amp;gt; y ? x : y) element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Maximum'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    *NOTE*: <c>Maximum</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor maximum (Tensor x, Tensor y, string name = "Maximum")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("Maximum", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the mean of elements across dimensions of a tensor.
        /// </summary>
        /// <param name="input">
        ///    The tensor to reduce.
        /// </param>
        /// <param name="reduction_indices">
        ///    The dimensions to reduce. Must be in the range
        ///    <c>[-rank(input), rank(input))</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Mean'.
        /// </param>
        /// <param name="keep_dims">
        ///    If true, retain reduced dimensions with length 1.
        /// </param>
        /// <returns>
        ///    The reduced tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Reduces <c>input</c> along the dimensions given in <c>axis</c>. Unless
        ///    <c>keep_dims</c> is true, the rank of the tensor is reduced by 1 for each entry in
        ///    <c>axis</c>. If <c>keep_dims</c> is true, the reduced dimensions are
        ///    retained with length 1.
        /// </remarks>
        public static Tensor mean (Tensor input, Tensor reduction_indices, bool? keep_dims = null, string name = "Mean")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["reduction_indices"] = reduction_indices;
            if (keep_dims.HasValue)
                dict["keep_dims"] = keep_dims.Value;
            var op = _op_def_lib._apply_op_helper("Mean", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Forwards the value of an available tensor from <c>inputs</c> to <c>output</c>.
        /// </summary>
        /// <param name="inputs">
        ///    The input tensors, exactly one of which will become available.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Merge'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output : Will be set to the available input tensor.
        ///    value_index : The index of the chosen input tensor in <c>inputs</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    <c>Merge</c> waits for at least one of the tensors in <c>inputs</c> to become available.
        ///    It is usually combined with <c>Switch</c> to implement branching.
        ///    
        ///    <c>Merge</c> forwards the first tensor to become available to <c>output</c>, and sets
        ///    <c>value_index</c> to its index in <c>inputs</c>.
        /// </remarks>
        public static (Tensor output, Tensor value_index) merge (Tensor[] inputs, string name = "Merge")
        {
            var dict = new Dictionary<string, object>();
            dict["inputs"] = inputs;
            var op = _op_def_lib._apply_op_helper("Merge", name: name, keywords: dict);
            int _idx = 0;
            var output = op.outputs[_idx++];
            var value_index = op.outputs[_idx++];
            return (output, value_index);
        }

        /// <summary>
        ///    Merges summaries.
        /// </summary>
        /// <param name="inputs">
        ///    Can be of any shape.  Each must contain serialized <c>Summary</c> protocol
        ///    buffers.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MergeSummary'.
        /// </param>
        /// <returns>
        ///    Scalar. Serialized <c>Summary</c> protocol buffer.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op creates a
        ///    [<c>Summary</c>](https://www.tensorflow.org/code/tensorflow/core/framework/summary.proto)
        ///    protocol buffer that contains the union of all the values in the input
        ///    summaries.
        ///    
        ///    When the Op is run, it reports an <c>InvalidArgument</c> error if multiple values
        ///    in the summaries to merge use the same tag.
        /// </remarks>
        public static Tensor merge_summary (Tensor[] inputs, string name = "MergeSummary")
        {
            var dict = new Dictionary<string, object>();
            dict["inputs"] = inputs;
            var op = _op_def_lib._apply_op_helper("MergeSummary", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    V2 format specific: merges the metadata files of sharded checkpoints.  The
        /// </summary>
        /// <param name="checkpoint_prefixes">
        ///    prefixes of V2 checkpoints to merge.
        /// </param>
        /// <param name="destination_prefix">
        ///    scalar.  The desired final prefix.  Allowed to be the same
        ///    as one of the checkpoint_prefixes.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MergeV2Checkpoints'.
        /// </param>
        /// <param name="delete_old_dirs">
        ///    see above.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    result is one logical checkpoint, with one physical metadata file and renamed
        ///    data files.
        ///    
        ///    Intended for "grouping" multiple checkpoints in a sharded checkpoint setup.
        ///    
        ///    If delete_old_dirs is true, attempts to delete recursively the dirname of each
        ///    path in the input checkpoint_prefixes.  This is useful when those paths are non
        ///    user-facing temporary locations.
        /// </remarks>
        public static Operation merge_v2checkpoints (Tensor checkpoint_prefixes, Tensor destination_prefix, bool? delete_old_dirs = null, string name = "MergeV2Checkpoints")
        {
            var dict = new Dictionary<string, object>();
            dict["checkpoint_prefixes"] = checkpoint_prefixes;
            dict["destination_prefix"] = destination_prefix;
            if (delete_old_dirs.HasValue)
                dict["delete_old_dirs"] = delete_old_dirs.Value;
            var op = _op_def_lib._apply_op_helper("MergeV2Checkpoints", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Transforms a spectrogram into a form that's useful for speech recognition.
        /// </summary>
        /// <param name="spectrogram">
        ///    Typically produced by the Spectrogram op, with magnitude_squared
        ///    set to true.
        /// </param>
        /// <param name="sample_rate">
        ///    How many samples per second the source audio used.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Mfcc'.
        /// </param>
        /// <param name="upper_frequency_limit">
        ///    The highest frequency to use when calculating the
        ///    ceptstrum.
        /// </param>
        /// <param name="lower_frequency_limit">
        ///    The lowest frequency to use when calculating the
        ///    ceptstrum.
        /// </param>
        /// <param name="filterbank_channel_count">
        ///    Resolution of the Mel bank used internally.
        /// </param>
        /// <param name="dct_coefficient_count">
        ///    How many output channels to produce per time slice.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Mel Frequency Cepstral Coefficients are a way of representing audio data that's
        ///    been effective as an input feature for machine learning. They are created by
        ///    taking the spectrum of a spectrogram (a 'cepstrum'), and discarding some of the
        ///    higher frequencies that are less significant to the human ear. They have a long
        ///    history in the speech recognition world, and https://en.wikipedia.org/wiki/Mel-frequency_cepstrum
        ///    is a good resource to learn more.
        /// </remarks>
        public static Tensor mfcc (Tensor spectrogram, Tensor sample_rate, float? upper_frequency_limit = null, float? lower_frequency_limit = null, int? filterbank_channel_count = null, int? dct_coefficient_count = null, string name = "Mfcc")
        {
            var dict = new Dictionary<string, object>();
            dict["spectrogram"] = spectrogram;
            dict["sample_rate"] = sample_rate;
            if (upper_frequency_limit.HasValue)
                dict["upper_frequency_limit"] = upper_frequency_limit.Value;
            if (lower_frequency_limit.HasValue)
                dict["lower_frequency_limit"] = lower_frequency_limit.Value;
            if (filterbank_channel_count.HasValue)
                dict["filterbank_channel_count"] = filterbank_channel_count.Value;
            if (dct_coefficient_count.HasValue)
                dict["dct_coefficient_count"] = dct_coefficient_count.Value;
            var op = _op_def_lib._apply_op_helper("Mfcc", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the minimum of elements across dimensions of a tensor.
        /// </summary>
        /// <param name="input">
        ///    The tensor to reduce.
        /// </param>
        /// <param name="reduction_indices">
        ///    The dimensions to reduce. Must be in the range
        ///    <c>[-rank(input), rank(input))</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Min'.
        /// </param>
        /// <param name="keep_dims">
        ///    If true, retain reduced dimensions with length 1.
        /// </param>
        /// <returns>
        ///    The reduced tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Reduces <c>input</c> along the dimensions given in <c>axis</c>. Unless
        ///    <c>keep_dims</c> is true, the rank of the tensor is reduced by 1 for each entry in
        ///    <c>axis</c>. If <c>keep_dims</c> is true, the reduced dimensions are
        ///    retained with length 1.
        /// </remarks>
        public static Tensor min (Tensor input, Tensor reduction_indices, bool? keep_dims = null, string name = "Min")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["reduction_indices"] = reduction_indices;
            if (keep_dims.HasValue)
                dict["keep_dims"] = keep_dims.Value;
            var op = _op_def_lib._apply_op_helper("Min", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the min of x and y (i.e. x &amp;lt; y ? x : y) element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Minimum'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    *NOTE*: <c>Minimum</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor minimum (Tensor x, Tensor y, string name = "Minimum")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("Minimum", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Pads a tensor with mirrored values.
        /// </summary>
        /// <param name="input">
        ///    The input tensor to be padded.
        /// </param>
        /// <param name="paddings">
        ///    A two-column matrix specifying the padding sizes. The number of
        ///    rows must be the same as the rank of <c>input</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MirrorPad'.
        /// </param>
        /// <param name="mode">
        ///    Optional argument
        ///    Either <c>REFLECT</c> or <c>SYMMETRIC</c>. In reflect mode the padded regions
        ///    do not include the borders, while in symmetric mode the padded regions
        ///    do include the borders. For example, if <c>input</c> is <c>[1, 2, 3]</c> and <c>paddings</c>
        ///    is <c>[0, 2]</c>, then the output is <c>[1, 2, 3, 2, 1]</c> in reflect mode, and
        ///    it is <c>[1, 2, 3, 3, 2]</c> in symmetric mode.
        /// </param>
        /// <returns>
        ///    The padded tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation pads a <c>input</c> with mirrored values according to the <c>paddings</c>
        ///    you specify. <c>paddings</c> is an integer tensor with shape <c>[n, 2]</c>, where n is
        ///    the rank of <c>input</c>. For each dimension D of <c>input</c>, <c>paddings[D, 0]</c> indicates
        ///    how many values to add before the contents of <c>input</c> in that dimension, and
        ///    <c>paddings[D, 1]</c> indicates how many values to add after the contents of <c>input</c>
        ///    in that dimension. Both <c>paddings[D, 0]</c> and <c>paddings[D, 1]</c> must be no greater
        ///    than <c>input.dim_size(D)</c> (or <c>input.dim_size(D) - 1</c>) if <c>copy_border</c> is true
        ///    (if false, respectively).
        ///    
        ///    The padded size of each dimension D of the output is:
        ///    
        ///    <c>paddings(D, 0) + input.dim_size(D) + paddings(D, 1)</c>
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # 't' is [[1, 2, 3], [4, 5, 6]].
        ///    # 'paddings' is [[1, 1]], [2, 2]].
        ///    # 'mode' is SYMMETRIC.
        ///    # rank of 't' is 2.
        ///    pad(t, paddings) ==&amp;gt; [[2, 1, 1, 2, 3, 3, 2]
        ///    [2, 1, 1, 2, 3, 3, 2]
        ///    [5, 4, 4, 5, 6, 6, 5]
        ///    [5, 4, 4, 5, 6, 6, 5]]
        ///   </code>
        /// </remarks>
        public static Tensor mirror_pad (Tensor input, Tensor paddings, string mode, string name = "MirrorPad")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["paddings"] = paddings;
            dict["mode"] = mode;
            var op = _op_def_lib._apply_op_helper("MirrorPad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Gradient op for <c>MirrorPad</c> op. This op folds a mirror-padded tensor.
        /// </summary>
        /// <param name="input">
        ///    The input tensor to be folded.
        /// </param>
        /// <param name="paddings">
        ///    A two-column matrix specifying the padding sizes. The number of
        ///    rows must be the same as the rank of <c>input</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MirrorPadGrad'.
        /// </param>
        /// <param name="mode">
        ///    Optional argument
        ///    The mode used in the <c>MirrorPad</c> op.
        /// </param>
        /// <returns>
        ///    The folded tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation folds the padded areas of <c>input</c> by <c>MirrorPad</c> according to the
        ///    <c>paddings</c> you specify. <c>paddings</c> must be the same as <c>paddings</c> argument
        ///    given to the corresponding <c>MirrorPad</c> op.
        ///    
        ///    The folded size of each dimension D of the output is:
        ///    
        ///    <c>input.dim_size(D) - paddings(D, 0) - paddings(D, 1)</c>
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # 't' is [[1, 2, 3], [4, 5, 6], [7, 8, 9]].
        ///    # 'paddings' is [[0, 1]], [0, 1]].
        ///    # 'mode' is SYMMETRIC.
        ///    # rank of 't' is 2.
        ///    pad(t, paddings) ==&amp;gt; [[ 1,  5]
        ///    [11, 28]]
        ///   </code>
        /// </remarks>
        public static Tensor mirror_pad_grad (Tensor input, Tensor paddings, string mode, string name = "MirrorPadGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["paddings"] = paddings;
            dict["mode"] = mode;
            var op = _op_def_lib._apply_op_helper("MirrorPadGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns element-wise remainder of division. This emulates C semantics in that
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Mod'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    the result here is consistent with a truncating divide. E.g.
        ///    <c>tf.truncatediv(x, y) * y + truncate_mod(x, y) = x</c>.
        ///    
        ///    *NOTE*: <c>Mod</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor mod (Tensor x, Tensor y, string name = "Mod")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("Mod", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns x * y element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Mul'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    *NOTE*: <c>Multiply</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor mul (Tensor x, Tensor y, string name = "Mul")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("Mul", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Draws samples from a multinomial distribution.
        /// </summary>
        /// <param name="logits">
        ///    2-D Tensor with shape <c>[batch_size, num_classes]</c>.  Each slice <c>[i, :]</c>
        ///    represents the unnormalized log probabilities for all classes.
        /// </param>
        /// <param name="num_samples">
        ///    0-D.  Number of independent samples to draw for each row slice.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Multinomial'.
        /// </param>
        /// <param name="seed">
        ///    If either seed or seed2 is set to be non-zero, the internal random number
        ///    generator is seeded by the given seed.  Otherwise, a random seed is used.
        /// </param>
        /// <param name="seed2">
        ///    A second seed to avoid seed collision.
        /// </param>
        /// <param name="output_dtype">
        /// </param>
        /// <returns>
        ///    2-D Tensor with shape <c>[batch_size, num_samples]</c>.  Each slice <c>[i, :]</c>
        ///    contains the drawn class labels with range <c>[0, num_classes)</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor multinomial (Tensor logits, Tensor num_samples, int? seed = null, int? seed2 = null, TF_DataType? output_dtype = null, string name = "Multinomial")
        {
            var dict = new Dictionary<string, object>();
            dict["logits"] = logits;
            dict["num_samples"] = num_samples;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            if (output_dtype.HasValue)
                dict["output_dtype"] = output_dtype.Value;
            var op = _op_def_lib._apply_op_helper("Multinomial", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates an empty hash table that uses tensors as the backing store.
        /// </summary>
        /// <param name="empty_key">
        ///    The key used to represent empty key buckets internally. Must not
        ///    be used in insert or lookup operations.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MutableDenseHashTable'.
        /// </param>
        /// <param name="value_dtype">
        ///    Optional argument
        ///    Type of the table values.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this table is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this table is shared under the given name across
        ///    multiple sessions.
        /// </param>
        /// <param name="use_node_name_sharing">
        /// </param>
        /// <param name="value_shape">
        ///    The shape of each value.
        /// </param>
        /// <param name="initial_num_buckets">
        ///    The initial number of hash table buckets. Must be a power
        ///    to 2.
        /// </param>
        /// <param name="max_load_factor">
        ///    The maximum ratio between number of entries and number of
        ///    buckets before growing the table. Must be between 0 and 1.
        /// </param>
        /// <returns>
        ///    Handle to a table.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    It uses "open addressing" with quadratic reprobing to resolve
        ///    collisions.
        ///    
        ///    This op creates a mutable hash table, specifying the type of its keys and
        ///    values. Each value must be a scalar. Data can be inserted into the table using
        ///    the insert operations. It does not support the initialization operation.
        /// </remarks>
        public static Tensor mutable_dense_hash_table (Tensor empty_key, TF_DataType value_dtype, string container = null, string shared_name = null, bool? use_node_name_sharing = null, TensorShape value_shape = null, int? initial_num_buckets = null, float? max_load_factor = null, string name = "MutableDenseHashTable")
        {
            var dict = new Dictionary<string, object>();
            dict["empty_key"] = empty_key;
            dict["value_dtype"] = value_dtype;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            if (use_node_name_sharing.HasValue)
                dict["use_node_name_sharing"] = use_node_name_sharing.Value;
            if (value_shape != null)
                dict["value_shape"] = value_shape;
            if (initial_num_buckets.HasValue)
                dict["initial_num_buckets"] = initial_num_buckets.Value;
            if (max_load_factor.HasValue)
                dict["max_load_factor"] = max_load_factor.Value;
            var op = _op_def_lib._apply_op_helper("MutableDenseHashTable", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates an empty hash table that uses tensors as the backing store.
        /// </summary>
        /// <param name="empty_key">
        ///    The key used to represent empty key buckets internally. Must not
        ///    be used in insert or lookup operations.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MutableDenseHashTableV2'.
        /// </param>
        /// <param name="value_dtype">
        ///    Optional argument
        ///    Type of the table values.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this table is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this table is shared under the given name across
        ///    multiple sessions.
        /// </param>
        /// <param name="use_node_name_sharing">
        /// </param>
        /// <param name="value_shape">
        ///    The shape of each value.
        /// </param>
        /// <param name="initial_num_buckets">
        ///    The initial number of hash table buckets. Must be a power
        ///    to 2.
        /// </param>
        /// <param name="max_load_factor">
        ///    The maximum ratio between number of entries and number of
        ///    buckets before growing the table. Must be between 0 and 1.
        /// </param>
        /// <returns>
        ///    Handle to a table.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    It uses "open addressing" with quadratic reprobing to resolve
        ///    collisions.
        ///    
        ///    This op creates a mutable hash table, specifying the type of its keys and
        ///    values. Each value must be a scalar. Data can be inserted into the table using
        ///    the insert operations. It does not support the initialization operation.
        /// </remarks>
        public static Tensor mutable_dense_hash_table_v2 (Tensor empty_key, TF_DataType value_dtype, string container = null, string shared_name = null, bool? use_node_name_sharing = null, TensorShape value_shape = null, int? initial_num_buckets = null, float? max_load_factor = null, string name = "MutableDenseHashTableV2")
        {
            var dict = new Dictionary<string, object>();
            dict["empty_key"] = empty_key;
            dict["value_dtype"] = value_dtype;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            if (use_node_name_sharing.HasValue)
                dict["use_node_name_sharing"] = use_node_name_sharing.Value;
            if (value_shape != null)
                dict["value_shape"] = value_shape;
            if (initial_num_buckets.HasValue)
                dict["initial_num_buckets"] = initial_num_buckets.Value;
            if (max_load_factor.HasValue)
                dict["max_load_factor"] = max_load_factor.Value;
            var op = _op_def_lib._apply_op_helper("MutableDenseHashTableV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates an empty hash table.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MutableHashTable'.
        /// </param>
        /// <param name="key_dtype">
        ///    Optional argument
        ///    Type of the table keys.
        /// </param>
        /// <param name="value_dtype">
        ///    Optional argument
        ///    Type of the table values.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this table is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this table is shared under the given name across
        ///    multiple sessions.
        /// </param>
        /// <param name="use_node_name_sharing">
        ///    If true and shared_name is empty, the table is shared
        ///    using the node name.
        /// </param>
        /// <returns>
        ///    Handle to a table.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op creates a mutable hash table, specifying the type of its keys and
        ///    values. Each value must be a scalar. Data can be inserted into the table using
        ///    the insert operations. It does not support the initialization operation.
        /// </remarks>
        public static Tensor mutable_hash_table (TF_DataType key_dtype, TF_DataType value_dtype, string container = null, string shared_name = null, bool? use_node_name_sharing = null, string name = "MutableHashTable")
        {
            var dict = new Dictionary<string, object>();
            dict["key_dtype"] = key_dtype;
            dict["value_dtype"] = value_dtype;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            if (use_node_name_sharing.HasValue)
                dict["use_node_name_sharing"] = use_node_name_sharing.Value;
            var op = _op_def_lib._apply_op_helper("MutableHashTable", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates an empty hash table.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MutableHashTableOfTensors'.
        /// </param>
        /// <param name="key_dtype">
        ///    Optional argument
        ///    Type of the table keys.
        /// </param>
        /// <param name="value_dtype">
        ///    Optional argument
        ///    Type of the table values.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this table is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this table is shared under the given name across
        ///    multiple sessions.
        /// </param>
        /// <param name="use_node_name_sharing">
        /// </param>
        /// <param name="value_shape">
        /// </param>
        /// <returns>
        ///    Handle to a table.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op creates a mutable hash table, specifying the type of its keys and
        ///    values. Each value must be a vector. Data can be inserted into the table using
        ///    the insert operations. It does not support the initialization operation.
        /// </remarks>
        public static Tensor mutable_hash_table_of_tensors (TF_DataType key_dtype, TF_DataType value_dtype, string container = null, string shared_name = null, bool? use_node_name_sharing = null, TensorShape value_shape = null, string name = "MutableHashTableOfTensors")
        {
            var dict = new Dictionary<string, object>();
            dict["key_dtype"] = key_dtype;
            dict["value_dtype"] = value_dtype;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            if (use_node_name_sharing.HasValue)
                dict["use_node_name_sharing"] = use_node_name_sharing.Value;
            if (value_shape != null)
                dict["value_shape"] = value_shape;
            var op = _op_def_lib._apply_op_helper("MutableHashTableOfTensors", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates an empty hash table.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MutableHashTableOfTensorsV2'.
        /// </param>
        /// <param name="key_dtype">
        ///    Optional argument
        ///    Type of the table keys.
        /// </param>
        /// <param name="value_dtype">
        ///    Optional argument
        ///    Type of the table values.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this table is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this table is shared under the given name across
        ///    multiple sessions.
        /// </param>
        /// <param name="use_node_name_sharing">
        /// </param>
        /// <param name="value_shape">
        /// </param>
        /// <returns>
        ///    Handle to a table.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op creates a mutable hash table, specifying the type of its keys and
        ///    values. Each value must be a vector. Data can be inserted into the table using
        ///    the insert operations. It does not support the initialization operation.
        /// </remarks>
        public static Tensor mutable_hash_table_of_tensors_v2 (TF_DataType key_dtype, TF_DataType value_dtype, string container = null, string shared_name = null, bool? use_node_name_sharing = null, TensorShape value_shape = null, string name = "MutableHashTableOfTensorsV2")
        {
            var dict = new Dictionary<string, object>();
            dict["key_dtype"] = key_dtype;
            dict["value_dtype"] = value_dtype;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            if (use_node_name_sharing.HasValue)
                dict["use_node_name_sharing"] = use_node_name_sharing.Value;
            if (value_shape != null)
                dict["value_shape"] = value_shape;
            var op = _op_def_lib._apply_op_helper("MutableHashTableOfTensorsV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates an empty hash table.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MutableHashTableV2'.
        /// </param>
        /// <param name="key_dtype">
        ///    Optional argument
        ///    Type of the table keys.
        /// </param>
        /// <param name="value_dtype">
        ///    Optional argument
        ///    Type of the table values.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this table is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this table is shared under the given name across
        ///    multiple sessions.
        /// </param>
        /// <param name="use_node_name_sharing">
        ///    If true and shared_name is empty, the table is shared
        ///    using the node name.
        /// </param>
        /// <returns>
        ///    Handle to a table.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op creates a mutable hash table, specifying the type of its keys and
        ///    values. Each value must be a scalar. Data can be inserted into the table using
        ///    the insert operations. It does not support the initialization operation.
        /// </remarks>
        public static Tensor mutable_hash_table_v2 (TF_DataType key_dtype, TF_DataType value_dtype, string container = null, string shared_name = null, bool? use_node_name_sharing = null, string name = "MutableHashTableV2")
        {
            var dict = new Dictionary<string, object>();
            dict["key_dtype"] = key_dtype;
            dict["value_dtype"] = value_dtype;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            if (use_node_name_sharing.HasValue)
                dict["use_node_name_sharing"] = use_node_name_sharing.Value;
            var op = _op_def_lib._apply_op_helper("MutableHashTableV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Locks a mutex resource.  The output is the lock.  So long as the lock tensor
        /// </summary>
        /// <param name="mutex">
        ///    The mutex resource to lock.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MutexLock'.
        /// </param>
        /// <returns>
        ///    A tensor that keeps a shared pointer to a lock on the mutex;
        ///    when the Tensor is destroyed, the use count on the shared pointer is decreased
        ///    by 1.  When it reaches 0, the lock is released.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    is alive, any other request to use <c>MutexLock</c> with this mutex will wait.
        ///    
        ///    This is particularly useful for creating a critical section when used in
        ///    conjunction with <c>MutexLockIdentity</c>:
        ///    
        ///   <code>
        ///    
        ///    mutex = mutex_v2(
        ///    shared_name=handle_name, container=container, name=name)
        ///    
        ///    def execute_in_critical_section(fn, *args, **kwargs):
        ///    lock = gen_resource_variable_ops.mutex_lock(mutex)
        ///    
        ///    with ops.control_dependencies([lock]):
        ///    r = fn(*args, **kwargs)
        ///    
        ///    with ops.control_dependencies(nest.flatten(r)):
        ///    with ops.colocate_with(mutex):
        ///    ensure_lock_exists = mutex_lock_identity(lock)
        ///    
        ///    # Make sure that if any element of r is accessed, all of
        ///    # them are executed together.
        ///    r = nest.map_structure(tf.identity, r)
        ///    
        ///    with ops.control_dependencies([ensure_lock_exists]):
        ///    return nest.map_structure(tf.identity, r)
        ///   </code>
        ///    
        ///    While <c>fn</c> is running in the critical section, no other functions which wish to
        ///    use this critical section may run.
        ///    
        ///    Often the use case is that two executions of the same graph, in parallel,
        ///    wish to run <c>fn</c>; and we wish to ensure that only one of them executes
        ///    at a time.  This is especially important if <c>fn</c> modifies one or more
        ///    variables at a time.
        ///    
        ///    It is also useful if two separate functions must share a resource, but we
        ///    wish to ensure the usage is exclusive.
        /// </remarks>
        public static Tensor mutex_lock (Tensor mutex, string name = "MutexLock")
        {
            var dict = new Dictionary<string, object>();
            dict["mutex"] = mutex;
            var op = _op_def_lib._apply_op_helper("MutexLock", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a Mutex resource that can be locked by <c>MutexLock</c>.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'MutexV2'.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this variable is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this variable is named in the given bucket
        ///    with this shared_name. Otherwise, the node name is used instead.
        /// </param>
        /// <returns>
        ///    The mutex resource.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor mutex_v2 (string container = null, string shared_name = null, string name = "MutexV2")
        {
            var dict = new Dictionary<string, object>();
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("MutexV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes numerical negative value element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Neg'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    I.e., \\(y = -x\\).
        /// </remarks>
        public static Tensor neg (Tensor x, string name = "Neg")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Neg", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Training via negative sampling.
        /// </summary>
        /// <param name="w_in">
        ///    input word embedding.
        /// </param>
        /// <param name="w_out">
        ///    output word embedding.
        /// </param>
        /// <param name="examples">
        ///    A vector of word ids.
        /// </param>
        /// <param name="labels">
        ///    A vector of word ids.
        /// </param>
        /// <param name="lr">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'NegTrain'.
        /// </param>
        /// <param name="vocab_count">
        ///    Optional argument
        ///    Count of words in the vocabulary.
        /// </param>
        /// <param name="num_negative_samples">
        ///    Optional argument
        ///    Number of negative samples per example.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation neg_train (Tensor w_in, Tensor w_out, Tensor examples, Tensor labels, Tensor lr, int[] vocab_count, int num_negative_samples, string name = "NegTrain")
        {
            var dict = new Dictionary<string, object>();
            dict["w_in"] = w_in;
            dict["w_out"] = w_out;
            dict["examples"] = examples;
            dict["labels"] = labels;
            dict["lr"] = lr;
            dict["vocab_count"] = vocab_count;
            dict["num_negative_samples"] = num_negative_samples;
            var op = _op_def_lib._apply_op_helper("NegTrain", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Makes its input available to the next iteration.
        /// </summary>
        /// <param name="data">
        ///    The tensor to be made available to the next iteration.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'NextIteration'.
        /// </param>
        /// <returns>
        ///    The same tensor as <c>data</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor next_iteration (Tensor data, string name = "NextIteration")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            var op = _op_def_lib._apply_op_helper("NextIteration", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Does nothing. Only useful as a placeholder for control edges.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'NoOp'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation no_op (string name = "NoOp")
        {
            var dict = new Dictionary<string, object>();
            var op = _op_def_lib._apply_op_helper("NoOp", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Greedily selects a subset of bounding boxes in descending order of score,
        /// </summary>
        /// <param name="boxes">
        ///    A 2-D float tensor of shape <c>[num_boxes, 4]</c>.
        /// </param>
        /// <param name="scores">
        ///    A 1-D float tensor of shape <c>[num_boxes]</c> representing a single
        ///    score corresponding to each box (each row of boxes).
        /// </param>
        /// <param name="max_output_size">
        ///    A scalar integer tensor representing the maximum number of
        ///    boxes to be selected by non max suppression.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'NonMaxSuppression'.
        /// </param>
        /// <param name="iou_threshold">
        ///    A float representing the threshold for deciding whether boxes
        ///    overlap too much with respect to IOU.
        /// </param>
        /// <returns>
        ///    A 1-D integer tensor of shape <c>[M]</c> representing the selected
        ///    indices from the boxes tensor, where <c>M &amp;lt;= max_output_size</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    pruning away boxes that have high intersection-over-union (IOU) overlap
        ///    with previously selected boxes.  Bounding boxes are supplied as
        ///    [y1, x1, y2, x2], where (y1, x1) and (y2, x2) are the coordinates of any
        ///    diagonal pair of box corners and the coordinates can be provided as normalized
        ///    (i.e., lying in the interval [0, 1]) or absolute.  Note that this algorithm
        ///    is agnostic to where the origin is in the coordinate system.  Note that this
        ///    algorithm is invariant to orthogonal transformations and translations
        ///    of the coordinate system; thus translating or reflections of the coordinate
        ///    system result in the same boxes being selected by the algorithm.
        ///    The output of this operation is a set of integers indexing into the input
        ///    collection of bounding boxes representing the selected boxes.  The bounding
        ///    box coordinates corresponding to the selected indices can then be obtained
        ///    using the <c>tf.gather operation</c>.  For example:
        ///    selected_indices = tf.image.non_max_suppression(
        ///    boxes, scores, max_output_size, iou_threshold)
        ///    selected_boxes = tf.gather(boxes, selected_indices)
        /// </remarks>
        public static Tensor non_max_suppression (Tensor boxes, Tensor scores, Tensor max_output_size, float? iou_threshold = null, string name = "NonMaxSuppression")
        {
            var dict = new Dictionary<string, object>();
            dict["boxes"] = boxes;
            dict["scores"] = scores;
            dict["max_output_size"] = max_output_size;
            if (iou_threshold.HasValue)
                dict["iou_threshold"] = iou_threshold.Value;
            var op = _op_def_lib._apply_op_helper("NonMaxSuppression", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Greedily selects a subset of bounding boxes in descending order of score,
        /// </summary>
        /// <param name="boxes">
        ///    A 2-D float tensor of shape <c>[num_boxes, 4]</c>.
        /// </param>
        /// <param name="scores">
        ///    A 1-D float tensor of shape <c>[num_boxes]</c> representing a single
        ///    score corresponding to each box (each row of boxes).
        /// </param>
        /// <param name="max_output_size">
        ///    A scalar integer tensor representing the maximum number of
        ///    boxes to be selected by non max suppression.
        /// </param>
        /// <param name="iou_threshold">
        ///    A 0-D float tensor representing the threshold for deciding whether
        ///    boxes overlap too much with respect to IOU.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'NonMaxSuppressionV2'.
        /// </param>
        /// <returns>
        ///    A 1-D integer tensor of shape <c>[M]</c> representing the selected
        ///    indices from the boxes tensor, where <c>M &amp;lt;= max_output_size</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    pruning away boxes that have high intersection-over-union (IOU) overlap
        ///    with previously selected boxes.  Bounding boxes are supplied as
        ///    [y1, x1, y2, x2], where (y1, x1) and (y2, x2) are the coordinates of any
        ///    diagonal pair of box corners and the coordinates can be provided as normalized
        ///    (i.e., lying in the interval [0, 1]) or absolute.  Note that this algorithm
        ///    is agnostic to where the origin is in the coordinate system.  Note that this
        ///    algorithm is invariant to orthogonal transformations and translations
        ///    of the coordinate system; thus translating or reflections of the coordinate
        ///    system result in the same boxes being selected by the algorithm.
        ///    
        ///    The output of this operation is a set of integers indexing into the input
        ///    collection of bounding boxes representing the selected boxes.  The bounding
        ///    box coordinates corresponding to the selected indices can then be obtained
        ///    using the <c>tf.gather operation</c>.  For example:
        ///    
        ///    selected_indices = tf.image.non_max_suppression_v2(
        ///    boxes, scores, max_output_size, iou_threshold)
        ///    selected_boxes = tf.gather(boxes, selected_indices)
        /// </remarks>
        public static Tensor non_max_suppression_v2 (Tensor boxes, Tensor scores, Tensor max_output_size, Tensor iou_threshold, string name = "NonMaxSuppressionV2")
        {
            var dict = new Dictionary<string, object>();
            dict["boxes"] = boxes;
            dict["scores"] = scores;
            dict["max_output_size"] = max_output_size;
            dict["iou_threshold"] = iou_threshold;
            var op = _op_def_lib._apply_op_helper("NonMaxSuppressionV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Greedily selects a subset of bounding boxes in descending order of score,
        /// </summary>
        /// <param name="boxes">
        ///    A 2-D float tensor of shape <c>[num_boxes, 4]</c>.
        /// </param>
        /// <param name="scores">
        ///    A 1-D float tensor of shape <c>[num_boxes]</c> representing a single
        ///    score corresponding to each box (each row of boxes).
        /// </param>
        /// <param name="max_output_size">
        ///    A scalar integer tensor representing the maximum number of
        ///    boxes to be selected by non max suppression.
        /// </param>
        /// <param name="iou_threshold">
        ///    A 0-D float tensor representing the threshold for deciding whether
        ///    boxes overlap too much with respect to IOU.
        /// </param>
        /// <param name="score_threshold">
        ///    A 0-D float tensor representing the threshold for deciding when to remove
        ///    boxes based on score.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'NonMaxSuppressionV3'.
        /// </param>
        /// <returns>
        ///    A 1-D integer tensor of shape <c>[M]</c> representing the selected
        ///    indices from the boxes tensor, where <c>M &amp;lt;= max_output_size</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    pruning away boxes that have high intersection-over-union (IOU) overlap
        ///    with previously selected boxes.  Bounding boxes with score less than
        ///    <c>score_threshold</c> are removed.  Bounding boxes are supplied as
        ///    [y1, x1, y2, x2], where (y1, x1) and (y2, x2) are the coordinates of any
        ///    diagonal pair of box corners and the coordinates can be provided as normalized
        ///    (i.e., lying in the interval [0, 1]) or absolute.  Note that this algorithm
        ///    is agnostic to where the origin is in the coordinate system and more
        ///    generally is invariant to orthogonal transformations and translations
        ///    of the coordinate system; thus translating or reflections of the coordinate
        ///    system result in the same boxes being selected by the algorithm.
        ///    The output of this operation is a set of integers indexing into the input
        ///    collection of bounding boxes representing the selected boxes.  The bounding
        ///    box coordinates corresponding to the selected indices can then be obtained
        ///    using the <c>tf.gather operation</c>.  For example:
        ///    selected_indices = tf.image.non_max_suppression_v2(
        ///    boxes, scores, max_output_size, iou_threshold, score_threshold)
        ///    selected_boxes = tf.gather(boxes, selected_indices)
        /// </remarks>
        public static Tensor non_max_suppression_v3 (Tensor boxes, Tensor scores, Tensor max_output_size, Tensor iou_threshold, Tensor score_threshold, string name = "NonMaxSuppressionV3")
        {
            var dict = new Dictionary<string, object>();
            dict["boxes"] = boxes;
            dict["scores"] = scores;
            dict["max_output_size"] = max_output_size;
            dict["iou_threshold"] = iou_threshold;
            dict["score_threshold"] = score_threshold;
            var op = _op_def_lib._apply_op_helper("NonMaxSuppressionV3", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Greedily selects a subset of bounding boxes in descending order of score,
        /// </summary>
        /// <param name="boxes">
        ///    A 2-D float tensor of shape <c>[num_boxes, 4]</c>.
        /// </param>
        /// <param name="scores">
        ///    A 1-D float tensor of shape <c>[num_boxes]</c> representing a single
        ///    score corresponding to each box (each row of boxes).
        /// </param>
        /// <param name="max_output_size">
        ///    A scalar integer tensor representing the maximum number of
        ///    boxes to be selected by non max suppression.
        /// </param>
        /// <param name="iou_threshold">
        ///    A 0-D float tensor representing the threshold for deciding whether
        ///    boxes overlap too much with respect to IOU.
        /// </param>
        /// <param name="score_threshold">
        ///    A 0-D float tensor representing the threshold for deciding when to remove
        ///    boxes based on score.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'NonMaxSuppressionV4'.
        /// </param>
        /// <param name="pad_to_max_output_size">
        ///    If true, the output <c>selected_indices</c> is padded to be of length
        ///    <c>max_output_size</c>. Defaults to false.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    selected_indices : A 1-D integer tensor of shape <c>[M]</c> representing the selected
        ///    indices from the boxes tensor, where <c>M &amp;lt;= max_output_size</c>.
        ///    valid_outputs : A 0-D integer tensor representing the number of valid elements in
        ///    <c>selected_indices</c>, with the valid elements appearing first.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    pruning away boxes that have high intersection-over-union (IOU) overlap
        ///    with previously selected boxes.  Bounding boxes with score less than
        ///    <c>score_threshold</c> are removed.  Bounding boxes are supplied as
        ///    [y1, x1, y2, x2], where (y1, x1) and (y2, x2) are the coordinates of any
        ///    diagonal pair of box corners and the coordinates can be provided as normalized
        ///    (i.e., lying in the interval [0, 1]) or absolute.  Note that this algorithm
        ///    is agnostic to where the origin is in the coordinate system and more
        ///    generally is invariant to orthogonal transformations and translations
        ///    of the coordinate system; thus translating or reflections of the coordinate
        ///    system result in the same boxes being selected by the algorithm.
        ///    The output of this operation is a set of integers indexing into the input
        ///    collection of bounding boxes representing the selected boxes.  The bounding
        ///    box coordinates corresponding to the selected indices can then be obtained
        ///    using the <c>tf.gather operation</c>.  For example:
        ///    selected_indices = tf.image.non_max_suppression_v2(
        ///    boxes, scores, max_output_size, iou_threshold, score_threshold)
        ///    selected_boxes = tf.gather(boxes, selected_indices)
        /// </remarks>
        public static (Tensor selected_indices, Tensor valid_outputs) non_max_suppression_v4 (Tensor boxes, Tensor scores, Tensor max_output_size, Tensor iou_threshold, Tensor score_threshold, bool? pad_to_max_output_size = null, string name = "NonMaxSuppressionV4")
        {
            var dict = new Dictionary<string, object>();
            dict["boxes"] = boxes;
            dict["scores"] = scores;
            dict["max_output_size"] = max_output_size;
            dict["iou_threshold"] = iou_threshold;
            dict["score_threshold"] = score_threshold;
            if (pad_to_max_output_size.HasValue)
                dict["pad_to_max_output_size"] = pad_to_max_output_size.Value;
            var op = _op_def_lib._apply_op_helper("NonMaxSuppressionV4", name: name, keywords: dict);
            int _idx = 0;
            var selected_indices = op.outputs[_idx++];
            var valid_outputs = op.outputs[_idx++];
            return (selected_indices, valid_outputs);
        }

        /// <summary>
        ///    Greedily selects a subset of bounding boxes in descending order of score,
        /// </summary>
        /// <param name="overlaps">
        ///    A 2-D float tensor of shape <c>[num_boxes, num_boxes]</c> representing
        ///    the n-by-n box overlap values.
        /// </param>
        /// <param name="scores">
        ///    A 1-D float tensor of shape <c>[num_boxes]</c> representing a single
        ///    score corresponding to each box (each row of boxes).
        /// </param>
        /// <param name="max_output_size">
        ///    A scalar integer tensor representing the maximum number of
        ///    boxes to be selected by non max suppression.
        /// </param>
        /// <param name="overlap_threshold">
        ///    A 0-D float tensor representing the threshold for deciding whether
        ///    boxes overlap too.
        /// </param>
        /// <param name="score_threshold">
        ///    A 0-D float tensor representing the threshold for deciding when to remove
        ///    boxes based on score.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'NonMaxSuppressionWithOverlaps'.
        /// </param>
        /// <returns>
        ///    A 1-D integer tensor of shape <c>[M]</c> representing the selected
        ///    indices from the boxes tensor, where <c>M &amp;lt;= max_output_size</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    pruning away boxes that have high overlaps
        ///    with previously selected boxes.  Bounding boxes with score less than
        ///    <c>score_threshold</c> are removed. N-by-n overlap values are supplied as square matrix,
        ///    which allows for defining a custom overlap criterium (eg. intersection over union,
        ///    intersection over area, etc.).
        ///    
        ///    The output of this operation is a set of integers indexing into the input
        ///    collection of bounding boxes representing the selected boxes.  The bounding
        ///    box coordinates corresponding to the selected indices can then be obtained
        ///    using the <c>tf.gather operation</c>.  For example:
        ///    
        ///    selected_indices = tf.image.non_max_suppression_with_overlaps(
        ///    overlaps, scores, max_output_size, overlap_threshold, score_threshold)
        ///    selected_boxes = tf.gather(boxes, selected_indices)
        /// </remarks>
        public static Tensor non_max_suppression_with_overlaps (Tensor overlaps, Tensor scores, Tensor max_output_size, Tensor overlap_threshold, Tensor score_threshold, string name = "NonMaxSuppressionWithOverlaps")
        {
            var dict = new Dictionary<string, object>();
            dict["overlaps"] = overlaps;
            dict["scores"] = scores;
            dict["max_output_size"] = max_output_size;
            dict["overlap_threshold"] = overlap_threshold;
            dict["score_threshold"] = score_threshold;
            var op = _op_def_lib._apply_op_helper("NonMaxSuppressionWithOverlaps", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the truth value of (x != y) element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'NotEqual'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    *NOTE*: <c>NotEqual</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor not_equal (Tensor x, Tensor y, string name = "NotEqual")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("NotEqual", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Finds values of the <c>n</c>-th order statistic for the last dimension.
        /// </summary>
        /// <param name="input">
        ///    1-D or higher with last dimension at least <c>n+1</c>.
        /// </param>
        /// <param name="n">
        ///    0-D. Position of sorted vector to select along the last dimension (along
        ///    each row for matrices). Valid range of n is <c>[0, input.shape[:-1])</c>
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'NthElement'.
        /// </param>
        /// <param name="reverse">
        ///    When set to True, find the nth-largest value in the vector and vice
        ///    versa.
        /// </param>
        /// <returns>
        ///    The <c>n</c>-th order statistic along each last dimensional slice.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    If the input is a vector (rank-1), finds the entries which is the nth-smallest
        ///    value in the vector and outputs their values as scalar tensor.
        ///    
        ///    For matrices (resp. higher rank input), computes the entries which is the
        ///    nth-smallest value in each row (resp. vector along the last dimension). Thus,
        ///    
        ///    values.shape = input.shape[:-1]
        /// </remarks>
        public static Tensor nth_element (Tensor input, Tensor n, bool? reverse = null, string name = "NthElement")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["n"] = n;
            if (reverse.HasValue)
                dict["reverse"] = reverse.Value;
            var op = _op_def_lib._apply_op_helper("NthElement", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns a one-hot tensor.
        /// </summary>
        /// <param name="indices">
        ///    A tensor of indices.
        /// </param>
        /// <param name="depth">
        ///    A scalar defining the depth of the one hot dimension.
        /// </param>
        /// <param name="on_value">
        ///    A scalar defining the value to fill in output when <c>indices[j] = i</c>.
        /// </param>
        /// <param name="off_value">
        ///    A scalar defining the value to fill in output when <c>indices[j] != i</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'OneHot'.
        /// </param>
        /// <param name="axis">
        ///    The axis to fill (default: -1, a new inner-most axis).
        /// </param>
        /// <returns>
        ///    The one-hot tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The locations represented by indices in <c>indices</c> take value <c>on_value</c>,
        ///    while all other locations take value <c>off_value</c>.
        ///    
        ///    If the input <c>indices</c> is rank <c>N</c>, the output will have rank <c>N+1</c>,
        ///    The new axis is created at dimension <c>axis</c> (default: the new axis is
        ///    appended at the end).
        ///    
        ///    If <c>indices</c> is a scalar the output shape will be a vector of length <c>depth</c>.
        ///    
        ///    If <c>indices</c> is a vector of length <c>features</c>, the output shape will be:
        ///   <code>
        ///    features x depth if axis == -1
        ///    depth x features if axis == 0
        ///   </code>
        ///    
        ///    If <c>indices</c> is a matrix (batch) with shape <c>[batch, features]</c>,
        ///    the output shape will be:
        ///   <code>
        ///    batch x features x depth if axis == -1
        ///    batch x depth x features if axis == 1
        ///    depth x batch x features if axis == 0
        ///   </code>
        ///    
        ///    
        ///    Examples
        ///    =========
        ///    
        ///    Suppose that
        ///    
        ///   <code>
        ///    indices = [0, 2, -1, 1]
        ///    depth = 3
        ///    on_value = 5.0
        ///    off_value = 0.0
        ///    axis = -1
        ///   </code>
        ///    
        ///    Then output is <c>[4 x 3]</c>:
        ///    
        ///   <code>
        ///    output =
        ///    [5.0 0.0 0.0]  // one_hot(0)
        ///    [0.0 0.0 5.0]  // one_hot(2)
        ///    [0.0 0.0 0.0]  // one_hot(-1)
        ///    [0.0 5.0 0.0]  // one_hot(1)
        ///   </code>
        ///    
        ///    Suppose that
        ///    
        ///   <code>
        ///    indices = [0, 2, -1, 1]
        ///    depth = 3
        ///    on_value = 0.0
        ///    off_value = 3.0
        ///    axis = 0
        ///   </code>
        ///    
        ///    Then output is <c>[3 x 4]</c>:
        ///    
        ///   <code>
        ///    output =
        ///    [0.0 3.0 3.0 3.0]
        ///    [3.0 3.0 3.0 0.0]
        ///    [3.0 3.0 3.0 3.0]
        ///    [3.0 0.0 3.0 3.0]
        ///    //  ^                one_hot(0)
        ///    //      ^            one_hot(2)
        ///    //          ^        one_hot(-1)
        ///    //              ^    one_hot(1)
        ///   </code>
        ///    Suppose that
        ///    
        ///   <code>
        ///    indices = [[0, 2], [1, -1]]
        ///    depth = 3
        ///    on_value = 1.0
        ///    off_value = 0.0
        ///    axis = -1
        ///   </code>
        ///    
        ///    Then output is <c>[2 x 2 x 3]</c>:
        ///    
        ///   <code>
        ///    output =
        ///    [
        ///    [1.0, 0.0, 0.0]  // one_hot(0)
        ///    [0.0, 0.0, 1.0]  // one_hot(2)
        ///    ][
        ///    [0.0, 1.0, 0.0]  // one_hot(1)
        ///    [0.0, 0.0, 0.0]  // one_hot(-1)
        ///    ]<c></c><c>
        /// </remarks>
        public static Tensor one_hot (Tensor indices, Tensor depth, Tensor on_value, Tensor off_value, int? axis = null, string name = "OneHot")
        {
            var dict = new Dictionary<string, object>();
            dict["indices"] = indices;
            dict["depth"] = depth;
            dict["on_value"] = on_value;
            dict["off_value"] = off_value;
            if (axis.HasValue)
                dict["axis"] = axis.Value;
            var op = _op_def_lib._apply_op_helper("OneHot", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns a tensor of ones with the same shape and type as x.
        /// </summary>
        /// <param name="x">
        ///    a tensor of type T.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'OnesLike'.
        /// </param>
        /// <returns>
        ///    a tensor of the same shape and type as x but filled with ones.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor ones_like (Tensor x, string name = "OnesLike")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("OnesLike", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a dataset by applying optimizations to <c>input_dataset</c>.
        /// </summary>
        /// <param name="input_dataset">
        ///    A variant tensor representing the input dataset.
        /// </param>
        /// <param name="optimizations">
        ///    A <c>tf.string</c> vector <c>tf.Tensor</c> identifying optimizations to use.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'OptimizeDataset'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Creates a dataset by applying optimizations to <c>input_dataset</c>.
        /// </remarks>
        public static Tensor optimize_dataset (Tensor input_dataset, Tensor optimizations, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "OptimizeDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["optimizations"] = optimizations;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("OptimizeDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Constructs an Optional variant from a tuple of tensors.
        /// </summary>
        /// <param name="components">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'OptionalFromValue'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor optional_from_value (Tensor[] components, string name = "OptionalFromValue")
        {
            var dict = new Dictionary<string, object>();
            dict["components"] = components;
            var op = _op_def_lib._apply_op_helper("OptionalFromValue", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the value stored in an Optional variant or raises an error if none exists.
        /// </summary>
        /// <param name="optional">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'OptionalGetValue'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor[] optional_get_value (Tensor optional, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "OptionalGetValue")
        {
            var dict = new Dictionary<string, object>();
            dict["optional"] = optional;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("OptionalGetValue", name: name, keywords: dict);
            int _idx = 0;
            var components = Enumerable.Range(0, op.OutputListLength("components")).Select(_ => op.outputs[_idx++]).ToArray();
            return (components);
        }

        /// <summary>
        ///    Returns true if and only if the given Optional variant has a value.
        /// </summary>
        /// <param name="optional">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'OptionalHasValue'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor optional_has_value (Tensor optional, string name = "OptionalHasValue")
        {
            var dict = new Dictionary<string, object>();
            dict["optional"] = optional;
            var op = _op_def_lib._apply_op_helper("OptionalHasValue", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates an Optional variant with no value.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'OptionalNone'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor optional_none (string name = "OptionalNone")
        {
            var dict = new Dictionary<string, object>();
            var op = _op_def_lib._apply_op_helper("OptionalNone", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Op removes all elements in the underlying container.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'OrderedMapClear'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        /// </param>
        /// <param name="capacity">
        /// </param>
        /// <param name="memory_limit">
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation ordered_map_clear (TF_DataType[] dtypes, int? capacity = null, int? memory_limit = null, string container = null, string shared_name = null, string name = "OrderedMapClear")
        {
            var dict = new Dictionary<string, object>();
            dict["dtypes"] = dtypes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (memory_limit.HasValue)
                dict["memory_limit"] = memory_limit.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("OrderedMapClear", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Op returns the number of incomplete elements in the underlying container.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'OrderedMapIncompleteSize'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        /// </param>
        /// <param name="capacity">
        /// </param>
        /// <param name="memory_limit">
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor ordered_map_incomplete_size (TF_DataType[] dtypes, int? capacity = null, int? memory_limit = null, string container = null, string shared_name = null, string name = "OrderedMapIncompleteSize")
        {
            var dict = new Dictionary<string, object>();
            dict["dtypes"] = dtypes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (memory_limit.HasValue)
                dict["memory_limit"] = memory_limit.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("OrderedMapIncompleteSize", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Op peeks at the values at the specified key.  If the
        /// </summary>
        /// <param name="key">
        /// </param>
        /// <param name="indices">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'OrderedMapPeek'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        /// </param>
        /// <param name="capacity">
        /// </param>
        /// <param name="memory_limit">
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    underlying container does not contain this key
        ///    this op will block until it does.   This Op is optimized for
        ///    performance.
        /// </remarks>
        public static Tensor[] ordered_map_peek (Tensor key, Tensor indices, TF_DataType[] dtypes, int? capacity = null, int? memory_limit = null, string container = null, string shared_name = null, string name = "OrderedMapPeek")
        {
            var dict = new Dictionary<string, object>();
            dict["key"] = key;
            dict["indices"] = indices;
            dict["dtypes"] = dtypes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (memory_limit.HasValue)
                dict["memory_limit"] = memory_limit.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("OrderedMapPeek", name: name, keywords: dict);
            int _idx = 0;
            var values = Enumerable.Range(0, op.OutputListLength("values")).Select(_ => op.outputs[_idx++]).ToArray();
            return (values);
        }

        /// <summary>
        ///    Op returns the number of elements in the underlying container.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'OrderedMapSize'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        /// </param>
        /// <param name="capacity">
        /// </param>
        /// <param name="memory_limit">
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor ordered_map_size (TF_DataType[] dtypes, int? capacity = null, int? memory_limit = null, string container = null, string shared_name = null, string name = "OrderedMapSize")
        {
            var dict = new Dictionary<string, object>();
            dict["dtypes"] = dtypes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (memory_limit.HasValue)
                dict["memory_limit"] = memory_limit.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("OrderedMapSize", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Stage (key, values) in the underlying container which behaves like a ordered
        /// </summary>
        /// <param name="key">
        ///    int64
        /// </param>
        /// <param name="indices">
        /// </param>
        /// <param name="values">
        ///    a list of tensors
        ///    dtypes A list of data types that inserted values should adhere to.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'OrderedMapStage'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        /// </param>
        /// <param name="capacity">
        ///    Maximum number of elements in the Staging Area. If &amp;gt; 0, inserts
        ///    on the container will block when the capacity is reached.
        /// </param>
        /// <param name="memory_limit">
        /// </param>
        /// <param name="container">
        ///    If non-empty, this queue is placed in the given container. Otherwise,
        ///    a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    It is necessary to match this name to the matching Unstage Op.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    associative container.   Elements are ordered by key.
        /// </remarks>
        public static Operation ordered_map_stage (Tensor key, Tensor indices, Tensor[] values, TF_DataType[] dtypes, int? capacity = null, int? memory_limit = null, string container = null, string shared_name = null, string name = "OrderedMapStage")
        {
            var dict = new Dictionary<string, object>();
            dict["key"] = key;
            dict["indices"] = indices;
            dict["values"] = values;
            dict["dtypes"] = dtypes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (memory_limit.HasValue)
                dict["memory_limit"] = memory_limit.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("OrderedMapStage", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Op removes and returns the values associated with the key
        /// </summary>
        /// <param name="key">
        /// </param>
        /// <param name="indices">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'OrderedMapUnstage'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        /// </param>
        /// <param name="capacity">
        /// </param>
        /// <param name="memory_limit">
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    from the underlying container.   If the underlying container
        ///    does not contain this key, the op will block until it does.
        /// </remarks>
        public static Tensor[] ordered_map_unstage (Tensor key, Tensor indices, TF_DataType[] dtypes, int? capacity = null, int? memory_limit = null, string container = null, string shared_name = null, string name = "OrderedMapUnstage")
        {
            var dict = new Dictionary<string, object>();
            dict["key"] = key;
            dict["indices"] = indices;
            dict["dtypes"] = dtypes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (memory_limit.HasValue)
                dict["memory_limit"] = memory_limit.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("OrderedMapUnstage", name: name, keywords: dict);
            int _idx = 0;
            var values = Enumerable.Range(0, op.OutputListLength("values")).Select(_ => op.outputs[_idx++]).ToArray();
            return (values);
        }

        /// <summary>
        ///    Op removes and returns the (key, value) element with the smallest
        /// </summary>
        /// <param name="indices">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'OrderedMapUnstageNoKey'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        /// </param>
        /// <param name="capacity">
        /// </param>
        /// <param name="memory_limit">
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    key :
        ///    values :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    key from the underlying container.   If the underlying container
        ///    does not contain elements, the op will block until it does.
        /// </remarks>
        public static (Tensor key, Tensor[] values) ordered_map_unstage_no_key (Tensor indices, TF_DataType[] dtypes, int? capacity = null, int? memory_limit = null, string container = null, string shared_name = null, string name = "OrderedMapUnstageNoKey")
        {
            var dict = new Dictionary<string, object>();
            dict["indices"] = indices;
            dict["dtypes"] = dtypes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (memory_limit.HasValue)
                dict["memory_limit"] = memory_limit.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("OrderedMapUnstageNoKey", name: name, keywords: dict);
            int _idx = 0;
            var key = op.outputs[_idx++];
            var values = Enumerable.Range(0, op.OutputListLength("values")).Select(_ => op.outputs[_idx++]).ToArray();
            return (key, values);
        }

        /// <summary>
        ///    Retrieves a single tensor from the computation outfeed.  This operation will
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'OutfeedDequeue'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The type of elements in the tensor.
        /// </param>
        /// <param name="shape">
        ///    Optional argument
        ///    The shape of the tensor.
        /// </param>
        /// <param name="device_ordinal">
        ///    The TPU device to use. This should be -1 when the Op
        ///    is running on a TPU device, and &amp;gt;= 0 when the Op is running on the CPU
        ///    device.
        /// </param>
        /// <returns>
        ///    A tensor that will be read from the device outfeed.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    block indefinitely until data is available.
        /// </remarks>
        public static Tensor outfeed_dequeue (TF_DataType dtype, TensorShape shape, int? device_ordinal = null, string name = "OutfeedDequeue")
        {
            var dict = new Dictionary<string, object>();
            dict["dtype"] = dtype;
            dict["shape"] = shape;
            if (device_ordinal.HasValue)
                dict["device_ordinal"] = device_ordinal.Value;
            var op = _op_def_lib._apply_op_helper("OutfeedDequeue", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Retrieve multiple values that will be emitted by the computation as an XLA
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'OutfeedDequeueTuple'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        ///    The element types of each element in <c>outputs</c>.
        /// </param>
        /// <param name="shapes">
        ///    Optional argument
        ///    The shapes of each tensor in <c>outputs</c>.
        /// </param>
        /// <param name="device_ordinal">
        ///    The TPU device to use. This should be -1 when the Op
        ///    is running on a TPU device, and &amp;gt;= 0 when the Op is running on the CPU
        ///    device.
        /// </param>
        /// <returns>
        ///    A list of tensors that will be read from the outfeed.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    tuple.  This operations will block indefinitely until data is available.
        ///    Output <c>i</c> corresponds to XLA tuple element <c>i</c>.
        /// </remarks>
        public static Tensor[] outfeed_dequeue_tuple (TF_DataType[] dtypes, TensorShape[] shapes, int? device_ordinal = null, string name = "OutfeedDequeueTuple")
        {
            var dict = new Dictionary<string, object>();
            dict["dtypes"] = dtypes;
            dict["shapes"] = shapes;
            if (device_ordinal.HasValue)
                dict["device_ordinal"] = device_ordinal.Value;
            var op = _op_def_lib._apply_op_helper("OutfeedDequeueTuple", name: name, keywords: dict);
            int _idx = 0;
            var outputs = Enumerable.Range(0, op.OutputListLength("outputs")).Select(_ => op.outputs[_idx++]).ToArray();
            return (outputs);
        }

        /// <summary>
        ///    An op which emits a single Tensor value from an XLA computation.
        /// </summary>
        /// <param name="input">
        ///    A tensor that will be inserted into the outfeed queue.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'OutfeedEnqueue'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation outfeed_enqueue (Tensor input, string name = "OutfeedEnqueue")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("OutfeedEnqueue", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    An op which emits multiple Tensor values from an XLA computation.
        /// </summary>
        /// <param name="inputs">
        ///    A list of tensors that will be inserted into the outfeed queue as an
        ///    XLA tuple.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'OutfeedEnqueueTuple'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation outfeed_enqueue_tuple (Tensor[] inputs, string name = "OutfeedEnqueueTuple")
        {
            var dict = new Dictionary<string, object>();
            dict["inputs"] = inputs;
            var op = _op_def_lib._apply_op_helper("OutfeedEnqueueTuple", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Packs a list of <c>N</c> rank-<c>R</c> tensors into one rank-<c>(R+1)</c> tensor.
        /// </summary>
        /// <param name="values">
        ///    Must be of same shape and type.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Pack'.
        /// </param>
        /// <param name="axis">
        ///    Dimension along which to pack.  Negative values wrap around, so the
        ///    valid range is <c>[-(R+1), R+1)</c>.
        /// </param>
        /// <returns>
        ///    The packed tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Packs the <c>N</c> tensors in <c>values</c> into a tensor with rank one higher than each
        ///    tensor in <c>values</c>, by packing them along the <c>axis</c> dimension.
        ///    Given a list of tensors of shape <c>(A, B, C)</c>;
        ///    
        ///    if <c>axis == 0</c> then the <c>output</c> tensor will have the shape <c>(N, A, B, C)</c>.
        ///    if <c>axis == 1</c> then the <c>output</c> tensor will have the shape <c>(A, N, B, C)</c>.
        ///    Etc.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # 'x' is [1, 4]
        ///    # 'y' is [2, 5]
        ///    # 'z' is [3, 6]
        ///    pack([x, y, z]) =&amp;gt; [[1, 4], [2, 5], [3, 6]]  # Pack along first dim.
        ///    pack([x, y, z], axis=1) =&amp;gt; [[1, 2, 3], [4, 5, 6]]
        ///   </code>
        ///    
        ///    This is the opposite of <c>unpack</c>.
        /// </remarks>
        public static Tensor pack (Tensor[] values, int? axis = null, string name = "Pack")
        {
            var dict = new Dictionary<string, object>();
            dict["values"] = values;
            if (axis.HasValue)
                dict["axis"] = axis.Value;
            var op = _op_def_lib._apply_op_helper("Pack", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Pads a tensor with zeros.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="paddings">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Pad'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation pads a <c>input</c> with zeros according to the <c>paddings</c> you
        ///    specify. <c>paddings</c> is an integer tensor with shape <c>[Dn, 2]</c>, where n is the
        ///    rank of <c>input</c>. For each dimension D of <c>input</c>, <c>paddings[D, 0]</c> indicates
        ///    how many zeros to add before the contents of <c>input</c> in that dimension, and
        ///    <c>paddings[D, 1]</c> indicates how many zeros to add after the contents of <c>input</c>
        ///    in that dimension.
        ///    
        ///    The padded size of each dimension D of the output is:
        ///    
        ///    <c>paddings(D, 0) + input.dim_size(D) + paddings(D, 1)</c>
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # 't' is [[1, 1], [2, 2]]
        ///    # 'paddings' is [[1, 1], [2, 2]]
        ///    # rank of 't' is 2
        ///    pad(t, paddings) ==&amp;gt; [[0, 0, 0, 0, 0, 0]
        ///    [0, 0, 1, 1, 0, 0]
        ///    [0, 0, 2, 2, 0, 0]
        ///    [0, 0, 0, 0, 0, 0]]
        ///   </code>
        ///    
        /// </remarks>
        public static Tensor pad (Tensor input, Tensor paddings, string name = "Pad")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["paddings"] = paddings;
            var op = _op_def_lib._apply_op_helper("Pad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Pads a tensor.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="paddings">
        /// </param>
        /// <param name="constant_values">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'PadV2'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation pads <c>input</c> according to the <c>paddings</c> and <c>constant_values</c>
        ///    you specify. <c>paddings</c> is an integer tensor with shape <c>[Dn, 2]</c>, where n is
        ///    the rank of <c>input</c>. For each dimension D of <c>input</c>, <c>paddings[D, 0]</c> indicates
        ///    how many padding values to add before the contents of <c>input</c> in that dimension,
        ///    and <c>paddings[D, 1]</c> indicates how many padding values to add after the contents
        ///    of <c>input</c> in that dimension. <c>constant_values</c> is a scalar tensor of the same
        ///    type as <c>input</c> that indicates the value to use for padding <c>input</c>.
        ///    
        ///    The padded size of each dimension D of the output is:
        ///    
        ///    <c>paddings(D, 0) + input.dim_size(D) + paddings(D, 1)</c>
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # 't' is [[1, 1], [2, 2]]
        ///    # 'paddings' is [[1, 1], [2, 2]]
        ///    # 'constant_values' is 0
        ///    # rank of 't' is 2
        ///    pad(t, paddings) ==&amp;gt; [[0, 0, 0, 0, 0, 0]
        ///    [0, 0, 1, 1, 0, 0]
        ///    [0, 0, 2, 2, 0, 0]
        ///    [0, 0, 0, 0, 0, 0]]
        ///   </code>
        /// </remarks>
        public static Tensor pad_v2 (Tensor input, Tensor paddings, Tensor constant_values, string name = "PadV2")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["paddings"] = paddings;
            dict["constant_values"] = constant_values;
            var op = _op_def_lib._apply_op_helper("PadV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a dataset that batches and pads <c>batch_size</c> elements from the input.
        /// </summary>
        /// <param name="input_dataset">
        /// </param>
        /// <param name="batch_size">
        ///    A scalar representing the number of elements to accumulate in a
        ///    batch.
        /// </param>
        /// <param name="padded_shapes">
        ///    A list of int64 tensors representing the desired padded shapes
        ///    of the corresponding output components. These shapes may be partially
        ///    specified, using <c>-1</c> to indicate that a particular dimension should be
        ///    padded to the maximum size of all batch elements.
        /// </param>
        /// <param name="padding_values">
        ///    A list of scalars containing the padding value to use for
        ///    each of the outputs.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'PaddedBatchDataset'.
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor padded_batch_dataset (Tensor input_dataset, Tensor batch_size, Tensor[] padded_shapes, Tensor[] padding_values, TensorShape[] output_shapes, string name = "PaddedBatchDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["batch_size"] = batch_size;
            dict["padded_shapes"] = padded_shapes;
            dict["padding_values"] = padding_values;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("PaddedBatchDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a dataset that batches and pads <c>batch_size</c> elements from the input.
        /// </summary>
        /// <param name="input_dataset">
        /// </param>
        /// <param name="batch_size">
        ///    A scalar representing the number of elements to accumulate in a
        ///    batch.
        /// </param>
        /// <param name="padded_shapes">
        ///    A list of int64 tensors representing the desired padded shapes
        ///    of the corresponding output components. These shapes may be partially
        ///    specified, using <c>-1</c> to indicate that a particular dimension should be
        ///    padded to the maximum size of all batch elements.
        /// </param>
        /// <param name="padding_values">
        ///    A list of scalars containing the padding value to use for
        ///    each of the outputs.
        /// </param>
        /// <param name="drop_remainder">
        ///    A scalar representing whether the last batch should be dropped in case its size
        ///    is smaller than desired.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'PaddedBatchDatasetV2'.
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor padded_batch_dataset_v2 (Tensor input_dataset, Tensor batch_size, Tensor[] padded_shapes, Tensor[] padding_values, Tensor drop_remainder, TensorShape[] output_shapes, string name = "PaddedBatchDatasetV2")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["batch_size"] = batch_size;
            dict["padded_shapes"] = padded_shapes;
            dict["padding_values"] = padding_values;
            dict["drop_remainder"] = drop_remainder;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("PaddedBatchDatasetV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A queue that produces elements in first-in first-out order.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'PaddingFIFOQueue'.
        /// </param>
        /// <param name="component_types">
        ///    Optional argument
        ///    The type of each component in a value.
        /// </param>
        /// <param name="shapes">
        ///    The shape of each component in a value. The length of this attr must
        ///    be either 0 or the same as the length of component_types.
        ///    Shapes of fixed rank but variable size are allowed by setting
        ///    any shape dimension to -1.  In this case, the inputs' shape may vary along
        ///    the given dimension, and DequeueMany will pad the given dimension with
        ///    zeros up to the maximum shape of all elements in the given batch.
        ///    If the length of this attr is 0, different queue elements may have
        ///    different ranks and shapes, but only one element may be dequeued at a time.
        /// </param>
        /// <param name="capacity">
        ///    The upper bound on the number of elements in this queue.
        ///    Negative numbers mean no limit.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this queue is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this queue will be shared under the given name
        ///    across multiple sessions.
        /// </param>
        /// <returns>
        ///    The handle to the queue.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Variable-size shapes are allowed by setting the corresponding shape dimensions
        ///    to 0 in the shape attr.  In this case DequeueMany will pad up to the maximum
        ///    size of any given element in the minibatch.  See below for details.
        /// </remarks>
        public static Tensor padding_f_i_f_o_queue (TF_DataType[] component_types, TensorShape[] shapes = null, int? capacity = null, string container = null, string shared_name = null, string name = "PaddingFIFOQueue")
        {
            var dict = new Dictionary<string, object>();
            dict["component_types"] = component_types;
            if (shapes != null)
                dict["shapes"] = shapes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("PaddingFIFOQueue", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A queue that produces elements in first-in first-out order.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'PaddingFIFOQueueV2'.
        /// </param>
        /// <param name="component_types">
        ///    Optional argument
        ///    The type of each component in a value.
        /// </param>
        /// <param name="shapes">
        ///    The shape of each component in a value. The length of this attr must
        ///    be either 0 or the same as the length of component_types.
        ///    Shapes of fixed rank but variable size are allowed by setting
        ///    any shape dimension to -1.  In this case, the inputs' shape may vary along
        ///    the given dimension, and DequeueMany will pad the given dimension with
        ///    zeros up to the maximum shape of all elements in the given batch.
        ///    If the length of this attr is 0, different queue elements may have
        ///    different ranks and shapes, but only one element may be dequeued at a time.
        /// </param>
        /// <param name="capacity">
        ///    The upper bound on the number of elements in this queue.
        ///    Negative numbers mean no limit.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this queue is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this queue will be shared under the given name
        ///    across multiple sessions.
        /// </param>
        /// <returns>
        ///    The handle to the queue.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Variable-size shapes are allowed by setting the corresponding shape dimensions
        ///    to 0 in the shape attr.  In this case DequeueMany will pad up to the maximum
        ///    size of any given element in the minibatch.  See below for details.
        /// </remarks>
        public static Tensor padding_f_i_f_o_queue_v2 (TF_DataType[] component_types, TensorShape[] shapes = null, int? capacity = null, string container = null, string shared_name = null, string name = "PaddingFIFOQueueV2")
        {
            var dict = new Dictionary<string, object>();
            dict["component_types"] = component_types;
            if (shapes != null)
                dict["shapes"] = shapes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("PaddingFIFOQueueV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Concatenates a list of <c>N</c> tensors along the first dimension.
        /// </summary>
        /// <param name="values">
        ///    Tensors to be concatenated. All must have size 1 in the first dimension
        ///    and same shape.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ParallelConcat'.
        /// </param>
        /// <param name="shape">
        ///    Optional argument
        ///    the final shape of the result; should be equal to the shapes of any input
        ///    but with the number of input values in the first dimension.
        /// </param>
        /// <returns>
        ///    The concatenated tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The input tensors are all required to have size 1 in the first dimension.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # 'x' is [[1, 4]]
        ///    # 'y' is [[2, 5]]
        ///    # 'z' is [[3, 6]]
        ///    parallel_concat([x, y, z]) =&amp;gt; [[1, 4], [2, 5], [3, 6]]  # Pack along first dim.
        ///   </code>
        ///    
        ///    The difference between concat and parallel_concat is that concat requires all
        ///    of the inputs be computed before the operation will begin but doesn't require
        ///    that the input shapes be known during graph construction.  Parallel concat
        ///    will copy pieces of the input into the output as they become available, in
        ///    some situations this can provide a performance benefit.
        /// </remarks>
        public static Tensor parallel_concat (Tensor[] values, TensorShape shape, string name = "ParallelConcat")
        {
            var dict = new Dictionary<string, object>();
            dict["values"] = values;
            dict["shape"] = shape;
            var op = _op_def_lib._apply_op_helper("ParallelConcat", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Interleave the values from the <c>data</c> tensors into a single tensor.
        /// </summary>
        /// <param name="indices">
        /// </param>
        /// <param name="data">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ParallelDynamicStitch'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Builds a merged tensor such that
        ///    
        ///   <code>
        ///    merged[indices[m][i, ..., j], ...] = data[m][i, ..., j, ...]
        ///   </code>
        ///    
        ///    For example, if each <c>indices[m]</c> is scalar or vector, we have
        ///    
        ///   <code>
        ///    # Scalar indices:
        ///    merged[indices[m], ...] = data[m][...]
        ///    
        ///    # Vector indices:
        ///    merged[indices[m][i], ...] = data[m][i, ...]
        ///   </code>
        ///    
        ///    Each <c>data[i].shape</c> must start with the corresponding <c>indices[i].shape</c>,
        ///    and the rest of <c>data[i].shape</c> must be constant w.r.t. <c>i</c>.  That is, we
        ///    must have <c>data[i].shape = indices[i].shape + constant</c>.  In terms of this
        ///    <c>constant</c>, the output shape is
        ///    
        ///    merged.shape = [max(indices)] + constant
        ///    
        ///    Values may be merged in parallel, so if an index appears in both <c>indices[m][i]</c>
        ///    and <c>indices[n][j]</c>, the result may be invalid. This differs from the normal
        ///    DynamicStitch operator that defines the behavior in that case.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    indices[0] = 6
        ///    indices[1] = [4, 1]
        ///    indices[2] = [[5, 2], [0, 3]]
        ///    data[0] = [61, 62]
        ///    data[1] = [[41, 42], [11, 12]]
        ///    data[2] = [[[51, 52], [21, 22]], [[1, 2], [31, 32]]]
        ///    merged = [[1, 2], [11, 12], [21, 22], [31, 32], [41, 42],
        ///    [51, 52], [61, 62]]
        ///   </code>
        ///    
        ///    This method can be used to merge partitions created by <c>dynamic_partition</c>
        ///    as illustrated on the following example:
        ///    
        ///   <code>
        ///    # Apply function (increments x_i) on elements for which a certain condition
        ///    # apply (x_i != -1 in this example).
        ///    x=tf.constant([0.1, -1., 5.2, 4.3, -1., 7.4])
        ///    condition_mask=tf.not_equal(x,tf.constant(-1.))
        ///    partitioned_data = tf.dynamic_partition(
        ///    x, tf.cast(condition_mask, tf.int32) , 2)
        ///    partitioned_data[1] = partitioned_data[1] + 1.0
        ///    condition_indices = tf.dynamic_partition(
        ///    tf.range(tf.shape(x)[0]), tf.cast(condition_mask, tf.int32) , 2)
        ///    x = tf.dynamic_stitch(condition_indices, partitioned_data)
        ///    # Here x=[1.1, -1., 6.2, 5.3, -1, 8.4], the -1. values remain
        ///    # unchanged.
        ///   </code>
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src="https://www.tensorflow.org/images/DynamicStitch.png" alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Tensor parallel_dynamic_stitch (Tensor[] indices, Tensor[] data, string name = "ParallelDynamicStitch")
        {
            var dict = new Dictionary<string, object>();
            dict["indices"] = indices;
            dict["data"] = data;
            var op = _op_def_lib._apply_op_helper("ParallelDynamicStitch", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Outputs random values from a normal distribution. The parameters may each be a
        /// </summary>
        /// <param name="shape">
        ///    The shape of the output tensor. Batches are indexed by the 0th dimension.
        /// </param>
        /// <param name="means">
        ///    The mean parameter of each batch.
        /// </param>
        /// <param name="stdevs">
        ///    The standard deviation parameter of each batch. Must be greater than 0.
        /// </param>
        /// <param name="minvals">
        ///    The minimum cutoff. May be -infinity.
        /// </param>
        /// <param name="maxvals">
        ///    The maximum cutoff. May be +infinity, and must be more than the minval
        ///    for each batch.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ParameterizedTruncatedNormal'.
        /// </param>
        /// <param name="seed">
        ///    If either <c>seed</c> or <c>seed2</c> are set to be non-zero, the random number
        ///    generator is seeded by the given seed.  Otherwise, it is seeded by a
        ///    random seed.
        /// </param>
        /// <param name="seed2">
        ///    A second seed to avoid seed collision.
        /// </param>
        /// <returns>
        ///    A matrix of shape num_batches x samples_per_batch, filled with random
        ///    truncated normal values using the parameters for each row.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    scalar which applies to the entire output, or a vector of length shape[0] which
        ///    stores the parameters for each batch.
        /// </remarks>
        public static Tensor parameterized_truncated_normal (Tensor shape, Tensor means, Tensor stdevs, Tensor minvals, Tensor maxvals, int? seed = null, int? seed2 = null, string name = "ParameterizedTruncatedNormal")
        {
            var dict = new Dictionary<string, object>();
            dict["shape"] = shape;
            dict["means"] = means;
            dict["stdevs"] = stdevs;
            dict["minvals"] = minvals;
            dict["maxvals"] = maxvals;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("ParameterizedTruncatedNormal", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Transforms a vector of brain.Example protos (as strings) into typed tensors.
        /// </summary>
        /// <param name="serialized">
        ///    A vector containing a batch of binary serialized Example protos.
        /// </param>
        /// <param name="names">
        ///    A vector containing the names of the serialized protos.
        ///    May contain, for example, table key (descriptive) names for the
        ///    corresponding serialized protos.  These are purely useful for debugging
        ///    purposes, and the presence of values here has no effect on the output.
        ///    May also be an empty vector if no names are available.
        ///    If non-empty, this vector must be the same length as "serialized".
        /// </param>
        /// <param name="sparse_keys">
        ///    A list of Nsparse string Tensors (scalars).
        ///    The keys expected in the Examples' features associated with sparse values.
        /// </param>
        /// <param name="dense_keys">
        ///    A list of Ndense string Tensors (scalars).
        ///    The keys expected in the Examples' features associated with dense values.
        /// </param>
        /// <param name="dense_defaults">
        ///    A list of Ndense Tensors (some may be empty).
        ///    dense_defaults[j] provides default values
        ///    when the example's feature_map lacks dense_key[j].  If an empty Tensor is
        ///    provided for dense_defaults[j], then the Feature dense_keys[j] is required.
        ///    The input type is inferred from dense_defaults[j], even when it's empty.
        ///    If dense_defaults[j] is not empty, and dense_shapes[j] is fully defined,
        ///    then the shape of dense_defaults[j] must match that of dense_shapes[j].
        ///    If dense_shapes[j] has an undefined major dimension (variable strides dense
        ///    feature), dense_defaults[j] must contain a single element:
        ///    the padding element.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ParseExample'.
        /// </param>
        /// <param name="sparse_types">
        ///    Optional argument
        ///    A list of Nsparse types; the data types of data in each Feature
        ///    given in sparse_keys.
        ///    Currently the ParseExample supports DT_FLOAT (FloatList),
        ///    DT_INT64 (Int64List), and DT_STRING (BytesList).
        /// </param>
        /// <param name="dense_shapes">
        ///    Optional argument
        ///    A list of Ndense shapes; the shapes of data in each Feature
        ///    given in dense_keys.
        ///    The number of elements in the Feature corresponding to dense_key[j]
        ///    must always equal dense_shapes[j].NumEntries().
        ///    If dense_shapes[j] == (D0, D1, ..., DN) then the shape of output
        ///    Tensor dense_values[j] will be (|serialized|, D0, D1, ..., DN):
        ///    The dense outputs are just the inputs row-stacked by batch.
        ///    This works for dense_shapes[j] = (-1, D1, ..., DN).  In this case
        ///    the shape of the output Tensor dense_values[j] will be
        ///    (|serialized|, M, D1, .., DN), where M is the maximum number of blocks
        ///    of elements of length D1 * .... * DN, across all minibatch entries
        ///    in the input.  Any minibatch entry with less than M blocks of elements of
        ///    length D1 * ... * DN will be padded with the corresponding default_value
        ///    scalar element along the second dimension.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    sparse_indices :
        ///    sparse_values :
        ///    sparse_shapes :
        ///    dense_values :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor[] sparse_indices, Tensor[] sparse_values, Tensor[] sparse_shapes, Tensor[] dense_values) parse_example (Tensor serialized, Tensor names, Tensor[] sparse_keys, Tensor[] dense_keys, Tensor[] dense_defaults, TF_DataType[] sparse_types, TensorShape[] dense_shapes, string name = "ParseExample")
        {
            var dict = new Dictionary<string, object>();
            dict["serialized"] = serialized;
            dict["names"] = names;
            dict["sparse_keys"] = sparse_keys;
            dict["dense_keys"] = dense_keys;
            dict["dense_defaults"] = dense_defaults;
            dict["sparse_types"] = sparse_types;
            dict["dense_shapes"] = dense_shapes;
            var op = _op_def_lib._apply_op_helper("ParseExample", name: name, keywords: dict);
            int _idx = 0;
            var sparse_indices = Enumerable.Range(0, op.OutputListLength("sparse_indices")).Select(_ => op.outputs[_idx++]).ToArray();
            var sparse_values = Enumerable.Range(0, op.OutputListLength("sparse_values")).Select(_ => op.outputs[_idx++]).ToArray();
            var sparse_shapes = Enumerable.Range(0, op.OutputListLength("sparse_shapes")).Select(_ => op.outputs[_idx++]).ToArray();
            var dense_values = Enumerable.Range(0, op.OutputListLength("dense_values")).Select(_ => op.outputs[_idx++]).ToArray();
            return (sparse_indices, sparse_values, sparse_shapes, dense_values);
        }

        /// <summary>
        ///    Transforms <c>input_dataset</c> containing <c>Example</c> protos as vectors of DT_STRING into a dataset of <c>Tensor</c> or <c>SparseTensor</c> objects representing the parsed features.
        /// </summary>
        /// <param name="input_dataset">
        /// </param>
        /// <param name="num_parallel_calls">
        /// </param>
        /// <param name="dense_defaults">
        ///    A dict mapping string keys to <c>Tensor</c>s.
        ///    The keys of the dict must match the dense_keys of the feature.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ParseExampleDataset'.
        /// </param>
        /// <param name="sparse_keys">
        ///    Optional argument
        ///    A list of string keys in the examples features.
        ///    The results for these keys will be returned as <c>SparseTensor</c> objects.
        /// </param>
        /// <param name="dense_keys">
        ///    Optional argument
        ///    A list of Ndense string Tensors (scalars).
        ///    The keys expected in the Examples features associated with dense values.
        /// </param>
        /// <param name="sparse_types">
        ///    Optional argument
        ///    A list of <c>DTypes</c> of the same length as <c>sparse_keys</c>.
        ///    Only <c>tf.float32</c> (<c>FloatList</c>), <c>tf.int64</c> (<c>Int64List</c>),
        ///    and <c>tf.string</c> (<c>BytesList</c>) are supported.
        /// </param>
        /// <param name="dense_shapes">
        ///    Optional argument
        ///    List of tuples with the same length as <c>dense_keys</c>.
        ///    The shape of the data for each dense feature referenced by <c>dense_keys</c>.
        ///    Required for any input tensors identified by <c>dense_keys</c>.  Must be
        ///    either fully defined, or may contain an unknown first dimension.
        ///    An unknown first dimension means the feature is treated as having
        ///    a variable number of blocks, and the output shape along this dimension
        ///    is considered unknown at graph build time.  Padding is applied for
        ///    minibatch elements smaller than the maximum number of blocks for the
        ///    given feature along this dimension.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        ///    The type list for the return values.
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        ///    The list of shapes being produced.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor parse_example_dataset (Tensor input_dataset, Tensor num_parallel_calls, Tensor[] dense_defaults, string[] sparse_keys, string[] dense_keys, TF_DataType[] sparse_types, TensorShape[] dense_shapes, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "ParseExampleDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["num_parallel_calls"] = num_parallel_calls;
            dict["dense_defaults"] = dense_defaults;
            dict["sparse_keys"] = sparse_keys;
            dict["dense_keys"] = dense_keys;
            dict["sparse_types"] = sparse_types;
            dict["dense_shapes"] = dense_shapes;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("ParseExampleDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Transforms a vector of brain.SequenceExample protos (as strings) into typed tensors.
        /// </summary>
        /// <param name="serialized">
        ///    A vector containing binary serialized SequenceExample protos.
        /// </param>
        /// <param name="debug_name">
        ///    A vector containing the names of the serialized protos.
        ///    May contain, for example, table key (descriptive) name for the
        ///    corresponding serialized proto.  This is purely useful for debugging
        ///    purposes, and the presence of values here has no effect on the output.
        ///    May also be an empty vector if no name is available.
        /// </param>
        /// <param name="context_dense_defaults">
        ///    A list of Ncontext_dense Tensors (some may be empty).
        ///    context_dense_defaults[j] provides default values
        ///    when the SequenceExample's context map lacks context_dense_key[j].
        ///    If an empty Tensor is provided for context_dense_defaults[j],
        ///    then the Feature context_dense_keys[j] is required.
        ///    The input type is inferred from context_dense_defaults[j], even when it's
        ///    empty.  If context_dense_defaults[j] is not empty, its shape must match
        ///    context_dense_shapes[j].
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ParseSequenceExample'.
        /// </param>
        /// <param name="feature_list_dense_missing_assumed_empty">
        ///    Optional argument
        ///    A vector listing the
        ///    FeatureList keys which may be missing from the SequenceExamples.  If the
        ///    associated FeatureList is missing, it is treated as empty.  By default,
        ///    any FeatureList not listed in this vector must exist in the SequenceExamples.
        /// </param>
        /// <param name="context_sparse_keys">
        ///    Optional argument
        ///    A list of Ncontext_sparse string Tensors (scalars).
        ///    The keys expected in the Examples' features associated with context_sparse
        ///    values.
        /// </param>
        /// <param name="context_dense_keys">
        ///    Optional argument
        ///    A list of Ncontext_dense string Tensors (scalars).
        ///    The keys expected in the SequenceExamples' context features associated with
        ///    dense values.
        /// </param>
        /// <param name="feature_list_sparse_keys">
        ///    Optional argument
        ///    A list of Nfeature_list_sparse string Tensors
        ///    (scalars).  The keys expected in the FeatureLists associated with sparse
        ///    values.
        /// </param>
        /// <param name="feature_list_dense_keys">
        ///    Optional argument
        ///    A list of Nfeature_list_dense string Tensors (scalars).
        ///    The keys expected in the SequenceExamples' feature_lists associated
        ///    with lists of dense values.
        /// </param>
        /// <param name="Ncontext_sparse">
        /// </param>
        /// <param name="Ncontext_dense">
        /// </param>
        /// <param name="Nfeature_list_sparse">
        /// </param>
        /// <param name="Nfeature_list_dense">
        /// </param>
        /// <param name="context_sparse_types">
        ///    A list of Ncontext_sparse types; the data types of data in
        ///    each context Feature given in context_sparse_keys.
        ///    Currently the ParseSingleSequenceExample supports DT_FLOAT (FloatList),
        ///    DT_INT64 (Int64List), and DT_STRING (BytesList).
        /// </param>
        /// <param name="feature_list_dense_types">
        /// </param>
        /// <param name="context_dense_shapes">
        ///    A list of Ncontext_dense shapes; the shapes of data in
        ///    each context Feature given in context_dense_keys.
        ///    The number of elements in the Feature corresponding to context_dense_key[j]
        ///    must always equal context_dense_shapes[j].NumEntries().
        ///    The shape of context_dense_values[j] will match context_dense_shapes[j].
        /// </param>
        /// <param name="feature_list_sparse_types">
        ///    A list of Nfeature_list_sparse types; the data types
        ///    of data in each FeatureList given in feature_list_sparse_keys.
        ///    Currently the ParseSingleSequenceExample supports DT_FLOAT (FloatList),
        ///    DT_INT64 (Int64List), and DT_STRING (BytesList).
        /// </param>
        /// <param name="feature_list_dense_shapes">
        ///    A list of Nfeature_list_dense shapes; the shapes of
        ///    data in each FeatureList given in feature_list_dense_keys.
        ///    The shape of each Feature in the FeatureList corresponding to
        ///    feature_list_dense_key[j] must always equal
        ///    feature_list_dense_shapes[j].NumEntries().
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    context_sparse_indices :
        ///    context_sparse_values :
        ///    context_sparse_shapes :
        ///    context_dense_values :
        ///    feature_list_sparse_indices :
        ///    feature_list_sparse_values :
        ///    feature_list_sparse_shapes :
        ///    feature_list_dense_values :
        ///    feature_list_dense_lengths :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor[] context_sparse_indices, Tensor[] context_sparse_values, Tensor[] context_sparse_shapes, Tensor[] context_dense_values, Tensor[] feature_list_sparse_indices, Tensor[] feature_list_sparse_values, Tensor[] feature_list_sparse_shapes, Tensor[] feature_list_dense_values, Tensor[] feature_list_dense_lengths) parse_sequence_example (Tensor serialized, Tensor debug_name, Tensor[] context_dense_defaults, string[] feature_list_dense_missing_assumed_empty, string[] context_sparse_keys, string[] context_dense_keys, string[] feature_list_sparse_keys, string[] feature_list_dense_keys, int? Ncontext_sparse = null, int? Ncontext_dense = null, int? Nfeature_list_sparse = null, int? Nfeature_list_dense = null, TF_DataType[] context_sparse_types = null, TF_DataType[] feature_list_dense_types = null, TensorShape[] context_dense_shapes = null, TF_DataType[] feature_list_sparse_types = null, TensorShape[] feature_list_dense_shapes = null, string name = "ParseSequenceExample")
        {
            var dict = new Dictionary<string, object>();
            dict["serialized"] = serialized;
            dict["debug_name"] = debug_name;
            dict["context_dense_defaults"] = context_dense_defaults;
            dict["feature_list_dense_missing_assumed_empty"] = feature_list_dense_missing_assumed_empty;
            dict["context_sparse_keys"] = context_sparse_keys;
            dict["context_dense_keys"] = context_dense_keys;
            dict["feature_list_sparse_keys"] = feature_list_sparse_keys;
            dict["feature_list_dense_keys"] = feature_list_dense_keys;
            if (Ncontext_sparse.HasValue)
                dict["Ncontext_sparse"] = Ncontext_sparse.Value;
            if (Ncontext_dense.HasValue)
                dict["Ncontext_dense"] = Ncontext_dense.Value;
            if (Nfeature_list_sparse.HasValue)
                dict["Nfeature_list_sparse"] = Nfeature_list_sparse.Value;
            if (Nfeature_list_dense.HasValue)
                dict["Nfeature_list_dense"] = Nfeature_list_dense.Value;
            if (context_sparse_types != null)
                dict["context_sparse_types"] = context_sparse_types;
            if (feature_list_dense_types != null)
                dict["feature_list_dense_types"] = feature_list_dense_types;
            if (context_dense_shapes != null)
                dict["context_dense_shapes"] = context_dense_shapes;
            if (feature_list_sparse_types != null)
                dict["feature_list_sparse_types"] = feature_list_sparse_types;
            if (feature_list_dense_shapes != null)
                dict["feature_list_dense_shapes"] = feature_list_dense_shapes;
            var op = _op_def_lib._apply_op_helper("ParseSequenceExample", name: name, keywords: dict);
            int _idx = 0;
            var context_sparse_indices = Enumerable.Range(0, op.OutputListLength("context_sparse_indices")).Select(_ => op.outputs[_idx++]).ToArray();
            var context_sparse_values = Enumerable.Range(0, op.OutputListLength("context_sparse_values")).Select(_ => op.outputs[_idx++]).ToArray();
            var context_sparse_shapes = Enumerable.Range(0, op.OutputListLength("context_sparse_shapes")).Select(_ => op.outputs[_idx++]).ToArray();
            var context_dense_values = Enumerable.Range(0, op.OutputListLength("context_dense_values")).Select(_ => op.outputs[_idx++]).ToArray();
            var feature_list_sparse_indices = Enumerable.Range(0, op.OutputListLength("feature_list_sparse_indices")).Select(_ => op.outputs[_idx++]).ToArray();
            var feature_list_sparse_values = Enumerable.Range(0, op.OutputListLength("feature_list_sparse_values")).Select(_ => op.outputs[_idx++]).ToArray();
            var feature_list_sparse_shapes = Enumerable.Range(0, op.OutputListLength("feature_list_sparse_shapes")).Select(_ => op.outputs[_idx++]).ToArray();
            var feature_list_dense_values = Enumerable.Range(0, op.OutputListLength("feature_list_dense_values")).Select(_ => op.outputs[_idx++]).ToArray();
            var feature_list_dense_lengths = Enumerable.Range(0, op.OutputListLength("feature_list_dense_lengths")).Select(_ => op.outputs[_idx++]).ToArray();
            return (context_sparse_indices, context_sparse_values, context_sparse_shapes, context_dense_values, feature_list_sparse_indices, feature_list_sparse_values, feature_list_sparse_shapes, feature_list_dense_values, feature_list_dense_lengths);
        }

        /// <summary>
        ///    Transforms a tf.Example proto (as a string) into typed tensors.
        /// </summary>
        /// <param name="serialized">
        ///    A vector containing a batch of binary serialized Example protos.
        /// </param>
        /// <param name="dense_defaults">
        ///    A list of Tensors (some may be empty), whose length matches
        ///    the length of <c>dense_keys</c>. dense_defaults[j] provides default values
        ///    when the example's feature_map lacks dense_key[j].  If an empty Tensor is
        ///    provided for dense_defaults[j], then the Feature dense_keys[j] is required.
        ///    The input type is inferred from dense_defaults[j], even when it's empty.
        ///    If dense_defaults[j] is not empty, and dense_shapes[j] is fully defined,
        ///    then the shape of dense_defaults[j] must match that of dense_shapes[j].
        ///    If dense_shapes[j] has an undefined major dimension (variable strides dense
        ///    feature), dense_defaults[j] must contain a single element:
        ///    the padding element.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ParseSingleExample'.
        /// </param>
        /// <param name="num_sparse">
        ///    Optional argument
        ///    The number of sparse features to be parsed from the example. This
        ///    must match the lengths of <c>sparse_keys</c> and <c>sparse_types</c>.
        /// </param>
        /// <param name="sparse_keys">
        ///    Optional argument
        ///    A list of <c>num_sparse</c> strings.
        ///    The keys expected in the Examples' features associated with sparse values.
        /// </param>
        /// <param name="dense_keys">
        ///    Optional argument
        ///    The keys expected in the Examples' features associated with dense
        ///    values.
        /// </param>
        /// <param name="sparse_types">
        ///    Optional argument
        ///    A list of <c>num_sparse</c> types; the data types of data in each
        ///    Feature given in sparse_keys.
        ///    Currently the ParseSingleExample op supports DT_FLOAT (FloatList),
        ///    DT_INT64 (Int64List), and DT_STRING (BytesList).
        /// </param>
        /// <param name="dense_shapes">
        ///    Optional argument
        ///    The shapes of data in each Feature given in dense_keys.
        ///    The length of this list must match the length of <c>dense_keys</c>.  The
        ///    number of elements in the Feature corresponding to dense_key[j] must
        ///    always equal dense_shapes[j].NumEntries().  If dense_shapes[j] ==
        ///    (D0, D1, ..., DN) then the shape of output Tensor dense_values[j]
        ///    will be (D0, D1, ..., DN): In the case dense_shapes[j] = (-1, D1,
        ///    ..., DN), the shape of the output Tensor dense_values[j] will be (M,
        ///    D1, .., DN), where M is the number of blocks of elements of length
        ///    D1 * .... * DN, in the input.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    sparse_indices :
        ///    sparse_values :
        ///    sparse_shapes :
        ///    dense_values :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor[] sparse_indices, Tensor[] sparse_values, Tensor[] sparse_shapes, Tensor[] dense_values) parse_single_example (Tensor serialized, Tensor[] dense_defaults, int num_sparse, string[] sparse_keys, string[] dense_keys, TF_DataType[] sparse_types, TensorShape[] dense_shapes, string name = "ParseSingleExample")
        {
            var dict = new Dictionary<string, object>();
            dict["serialized"] = serialized;
            dict["dense_defaults"] = dense_defaults;
            dict["num_sparse"] = num_sparse;
            dict["sparse_keys"] = sparse_keys;
            dict["dense_keys"] = dense_keys;
            dict["sparse_types"] = sparse_types;
            dict["dense_shapes"] = dense_shapes;
            var op = _op_def_lib._apply_op_helper("ParseSingleExample", name: name, keywords: dict);
            int _idx = 0;
            var sparse_indices = Enumerable.Range(0, op.OutputListLength("sparse_indices")).Select(_ => op.outputs[_idx++]).ToArray();
            var sparse_values = Enumerable.Range(0, op.OutputListLength("sparse_values")).Select(_ => op.outputs[_idx++]).ToArray();
            var sparse_shapes = Enumerable.Range(0, op.OutputListLength("sparse_shapes")).Select(_ => op.outputs[_idx++]).ToArray();
            var dense_values = Enumerable.Range(0, op.OutputListLength("dense_values")).Select(_ => op.outputs[_idx++]).ToArray();
            return (sparse_indices, sparse_values, sparse_shapes, dense_values);
        }

        /// <summary>
        ///    Transforms a scalar brain.SequenceExample proto (as strings) into typed tensors.
        /// </summary>
        /// <param name="serialized">
        ///    A scalar containing a binary serialized SequenceExample proto.
        /// </param>
        /// <param name="feature_list_dense_missing_assumed_empty">
        ///    A vector listing the
        ///    FeatureList keys which may be missing from the SequenceExample.  If the
        ///    associated FeatureList is missing, it is treated as empty.  By default,
        ///    any FeatureList not listed in this vector must exist in the SequenceExample.
        /// </param>
        /// <param name="context_sparse_keys">
        ///    A list of Ncontext_sparse string Tensors (scalars).
        ///    The keys expected in the Examples' features associated with context_sparse
        ///    values.
        /// </param>
        /// <param name="context_dense_keys">
        ///    A list of Ncontext_dense string Tensors (scalars).
        ///    The keys expected in the SequenceExamples' context features associated with
        ///    dense values.
        /// </param>
        /// <param name="feature_list_sparse_keys">
        ///    A list of Nfeature_list_sparse string Tensors
        ///    (scalars).  The keys expected in the FeatureLists associated with sparse
        ///    values.
        /// </param>
        /// <param name="feature_list_dense_keys">
        ///    A list of Nfeature_list_dense string Tensors (scalars).
        ///    The keys expected in the SequenceExamples' feature_lists associated
        ///    with lists of dense values.
        /// </param>
        /// <param name="context_dense_defaults">
        ///    A list of Ncontext_dense Tensors (some may be empty).
        ///    context_dense_defaults[j] provides default values
        ///    when the SequenceExample's context map lacks context_dense_key[j].
        ///    If an empty Tensor is provided for context_dense_defaults[j],
        ///    then the Feature context_dense_keys[j] is required.
        ///    The input type is inferred from context_dense_defaults[j], even when it's
        ///    empty.  If context_dense_defaults[j] is not empty, its shape must match
        ///    context_dense_shapes[j].
        /// </param>
        /// <param name="debug_name">
        ///    A scalar containing the name of the serialized proto.
        ///    May contain, for example, table key (descriptive) name for the
        ///    corresponding serialized proto.  This is purely useful for debugging
        ///    purposes, and the presence of values here has no effect on the output.
        ///    May also be an empty scalar if no name is available.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ParseSingleSequenceExample'.
        /// </param>
        /// <param name="context_sparse_types">
        ///    A list of Ncontext_sparse types; the data types of data in
        ///    each context Feature given in context_sparse_keys.
        ///    Currently the ParseSingleSequenceExample supports DT_FLOAT (FloatList),
        ///    DT_INT64 (Int64List), and DT_STRING (BytesList).
        /// </param>
        /// <param name="feature_list_dense_types">
        /// </param>
        /// <param name="context_dense_shapes">
        ///    A list of Ncontext_dense shapes; the shapes of data in
        ///    each context Feature given in context_dense_keys.
        ///    The number of elements in the Feature corresponding to context_dense_key[j]
        ///    must always equal context_dense_shapes[j].NumEntries().
        ///    The shape of context_dense_values[j] will match context_dense_shapes[j].
        /// </param>
        /// <param name="feature_list_sparse_types">
        ///    A list of Nfeature_list_sparse types; the data types
        ///    of data in each FeatureList given in feature_list_sparse_keys.
        ///    Currently the ParseSingleSequenceExample supports DT_FLOAT (FloatList),
        ///    DT_INT64 (Int64List), and DT_STRING (BytesList).
        /// </param>
        /// <param name="feature_list_dense_shapes">
        ///    A list of Nfeature_list_dense shapes; the shapes of
        ///    data in each FeatureList given in feature_list_dense_keys.
        ///    The shape of each Feature in the FeatureList corresponding to
        ///    feature_list_dense_key[j] must always equal
        ///    feature_list_dense_shapes[j].NumEntries().
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    context_sparse_indices :
        ///    context_sparse_values :
        ///    context_sparse_shapes :
        ///    context_dense_values :
        ///    feature_list_sparse_indices :
        ///    feature_list_sparse_values :
        ///    feature_list_sparse_shapes :
        ///    feature_list_dense_values :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor[] context_sparse_indices, Tensor[] context_sparse_values, Tensor[] context_sparse_shapes, Tensor[] context_dense_values, Tensor[] feature_list_sparse_indices, Tensor[] feature_list_sparse_values, Tensor[] feature_list_sparse_shapes, Tensor[] feature_list_dense_values) parse_single_sequence_example (Tensor serialized, Tensor feature_list_dense_missing_assumed_empty, Tensor[] context_sparse_keys, Tensor[] context_dense_keys, Tensor[] feature_list_sparse_keys, Tensor[] feature_list_dense_keys, Tensor[] context_dense_defaults, Tensor debug_name, TF_DataType[] context_sparse_types = null, TF_DataType[] feature_list_dense_types = null, TensorShape[] context_dense_shapes = null, TF_DataType[] feature_list_sparse_types = null, TensorShape[] feature_list_dense_shapes = null, string name = "ParseSingleSequenceExample")
        {
            var dict = new Dictionary<string, object>();
            dict["serialized"] = serialized;
            dict["feature_list_dense_missing_assumed_empty"] = feature_list_dense_missing_assumed_empty;
            dict["context_sparse_keys"] = context_sparse_keys;
            dict["context_dense_keys"] = context_dense_keys;
            dict["feature_list_sparse_keys"] = feature_list_sparse_keys;
            dict["feature_list_dense_keys"] = feature_list_dense_keys;
            dict["context_dense_defaults"] = context_dense_defaults;
            dict["debug_name"] = debug_name;
            if (context_sparse_types != null)
                dict["context_sparse_types"] = context_sparse_types;
            if (feature_list_dense_types != null)
                dict["feature_list_dense_types"] = feature_list_dense_types;
            if (context_dense_shapes != null)
                dict["context_dense_shapes"] = context_dense_shapes;
            if (feature_list_sparse_types != null)
                dict["feature_list_sparse_types"] = feature_list_sparse_types;
            if (feature_list_dense_shapes != null)
                dict["feature_list_dense_shapes"] = feature_list_dense_shapes;
            var op = _op_def_lib._apply_op_helper("ParseSingleSequenceExample", name: name, keywords: dict);
            int _idx = 0;
            var context_sparse_indices = Enumerable.Range(0, op.OutputListLength("context_sparse_indices")).Select(_ => op.outputs[_idx++]).ToArray();
            var context_sparse_values = Enumerable.Range(0, op.OutputListLength("context_sparse_values")).Select(_ => op.outputs[_idx++]).ToArray();
            var context_sparse_shapes = Enumerable.Range(0, op.OutputListLength("context_sparse_shapes")).Select(_ => op.outputs[_idx++]).ToArray();
            var context_dense_values = Enumerable.Range(0, op.OutputListLength("context_dense_values")).Select(_ => op.outputs[_idx++]).ToArray();
            var feature_list_sparse_indices = Enumerable.Range(0, op.OutputListLength("feature_list_sparse_indices")).Select(_ => op.outputs[_idx++]).ToArray();
            var feature_list_sparse_values = Enumerable.Range(0, op.OutputListLength("feature_list_sparse_values")).Select(_ => op.outputs[_idx++]).ToArray();
            var feature_list_sparse_shapes = Enumerable.Range(0, op.OutputListLength("feature_list_sparse_shapes")).Select(_ => op.outputs[_idx++]).ToArray();
            var feature_list_dense_values = Enumerable.Range(0, op.OutputListLength("feature_list_dense_values")).Select(_ => op.outputs[_idx++]).ToArray();
            return (context_sparse_indices, context_sparse_values, context_sparse_shapes, context_dense_values, feature_list_sparse_indices, feature_list_sparse_values, feature_list_sparse_shapes, feature_list_dense_values);
        }

        /// <summary>
        ///    Transforms a serialized tensorflow.TensorProto proto into a Tensor.
        /// </summary>
        /// <param name="serialized">
        ///    A scalar string containing a serialized TensorProto proto.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ParseTensor'.
        /// </param>
        /// <param name="out_type">
        ///    Optional argument
        ///    The type of the serialized tensor.  The provided type must match the
        ///    type of the serialized tensor and no implicit conversion will take place.
        /// </param>
        /// <returns>
        ///    A Tensor of type <c>out_type</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor parse_tensor (Tensor serialized, TF_DataType out_type, string name = "ParseTensor")
        {
            var dict = new Dictionary<string, object>();
            dict["serialized"] = serialized;
            dict["out_type"] = out_type;
            var op = _op_def_lib._apply_op_helper("ParseTensor", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A placeholder op for a value that will be fed into the computation.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Placeholder'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The type of elements in the tensor.
        /// </param>
        /// <param name="shape">
        ///    (Optional) The shape of the tensor. If the shape has 0 dimensions, the
        ///    shape is unconstrained.
        /// </param>
        /// <returns>
        ///    A placeholder tensor that must be replaced using the feed mechanism.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    N.B. This operation will fail with an error if it is executed. It is
        ///    intended as a way to represent a value that will always be fed, and to
        ///    provide attrs that enable the fed value to be checked at runtime.
        /// </remarks>
        public static Tensor placeholder (TF_DataType dtype, TensorShape shape = null, string name = "Placeholder")
        {
            var dict = new Dictionary<string, object>();
            dict["dtype"] = dtype;
            if (shape != null)
                dict["shape"] = shape;
            var op = _op_def_lib._apply_op_helper("Placeholder", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A placeholder op for a value that will be fed into the computation.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'PlaceholderV2'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The type of elements in the tensor.
        /// </param>
        /// <param name="shape">
        ///    Optional argument
        ///    The shape of the tensor. The shape can be any partially-specified
        ///    shape.  To be unconstrained, pass in a shape with unknown rank.
        /// </param>
        /// <returns>
        ///    A placeholder tensor that must be replaced using the feed mechanism.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    N.B. This operation will fail with an error if it is executed. It is
        ///    intended as a way to represent a value that will always be fed, and to
        ///    provide attrs that enable the fed value to be checked at runtime.
        /// </remarks>
        public static Tensor placeholder_v2 (TF_DataType dtype, TensorShape shape, string name = "PlaceholderV2")
        {
            var dict = new Dictionary<string, object>();
            dict["dtype"] = dtype;
            dict["shape"] = shape;
            var op = _op_def_lib._apply_op_helper("PlaceholderV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A placeholder op that passes through <c>input</c> when its output is not fed.
        /// </summary>
        /// <param name="input">
        ///    The default value to produce when <c>output</c> is not fed.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'PlaceholderWithDefault'.
        /// </param>
        /// <param name="shape">
        ///    Optional argument
        ///    The (possibly partial) shape of the tensor.
        /// </param>
        /// <returns>
        ///    A placeholder tensor that defaults to <c>input</c> if it is not fed.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor placeholder_with_default (Tensor input, TensorShape shape, string name = "PlaceholderWithDefault")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["shape"] = shape;
            var op = _op_def_lib._apply_op_helper("PlaceholderWithDefault", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Compute the polygamma function \\(\psi^{(n)}(x)\\).
        /// </summary>
        /// <param name="a">
        /// </param>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Polygamma'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The polygamma function is defined as:
        ///    
        ///    
        ///    \\(\psi^{(n)}(x) = \frac{d^n}{dx^n} \psi(x)\\)
        ///    
        ///    where \\(\psi(x)\\) is the digamma function.
        /// </remarks>
        public static Tensor polygamma (Tensor a, Tensor x, string name = "Polygamma")
        {
            var dict = new Dictionary<string, object>();
            dict["a"] = a;
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Polygamma", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes element-wise population count (a.k.a. popcount, bitsum, bitcount).
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'PopulationCount'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    For each entry in <c>x</c>, calculates the number of <c>1</c> (on) bits in the binary
        ///    representation of that entry.
        ///    
        ///    **NOTE**: It is more efficient to first <c>tf.bitcast</c> your tensors into
        ///    <c>int32</c> or <c>int64</c> and perform the bitcount on the result, than to feed in
        ///    8- or 16-bit inputs and then aggregate the resulting counts.
        /// </remarks>
        public static Tensor population_count (Tensor x, string name = "PopulationCount")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("PopulationCount", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the power of one value to another.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Pow'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given a tensor <c>x</c> and a tensor <c>y</c>, this operation computes \\(x^y\\) for
        ///    corresponding elements in <c>x</c> and <c>y</c>. For example:
        ///    
        ///   <code>
        ///    # tensor 'x' is [[2, 2]], [3, 3]]
        ///    # tensor 'y' is [[8, 16], [2, 3]]
        ///    tf.pow(x, y) ==&amp;gt; [[256, 65536], [9, 27]]
        ///   </code>
        /// </remarks>
        public static Tensor pow (Tensor x, Tensor y, string name = "Pow")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("Pow", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a dataset that asynchronously prefetches elements from <c>input_dataset</c>.
        /// </summary>
        /// <param name="input_dataset">
        /// </param>
        /// <param name="buffer_size">
        ///    The maximum number of elements to buffer in an iterator over
        ///    this dataset.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'PrefetchDataset'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor prefetch_dataset (Tensor input_dataset, Tensor buffer_size, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "PrefetchDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["buffer_size"] = buffer_size;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("PrefetchDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    An identity op that triggers an error if a gradient is requested.
        /// </summary>
        /// <param name="input">
        ///    any tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'PreventGradient'.
        /// </param>
        /// <param name="message">
        ///    Will be printed in the error when anyone tries to differentiate
        ///    this operation.
        /// </param>
        /// <returns>
        ///    the same input tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    When executed in a graph, this op outputs its input tensor as-is.
        ///    
        ///    When building ops to compute gradients, the TensorFlow gradient system
        ///    will return an error when trying to lookup the gradient of this op,
        ///    because no gradient must ever be registered for this function.  This
        ///    op exists to prevent subtle bugs from silently returning unimplemented
        ///    gradients in some corner cases.
        /// </remarks>
        public static Tensor prevent_gradient (Tensor input, string message = null, string name = "PreventGradient")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (message != null)
                dict["message"] = message;
            var op = _op_def_lib._apply_op_helper("PreventGradient", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Prints a list of tensors.
        /// </summary>
        /// <param name="input">
        ///    The tensor passed to <c>output</c>
        /// </param>
        /// <param name="data">
        ///    A list of tensors to print out when op is evaluated.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Print'.
        /// </param>
        /// <param name="message">
        ///    A string, prefix of the error message.
        /// </param>
        /// <param name="first_n">
        ///    Only log <c>first_n</c> number of times. -1 disables logging.
        /// </param>
        /// <param name="summarize">
        ///    Only print this many entries of each tensor.
        /// </param>
        /// <returns>
        ///    = The unmodified <c>input</c> tensor
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Passes <c>input</c> through to <c>output</c> and prints <c>data</c> when evaluating.
        /// </remarks>
        public static Tensor print (Tensor input, Tensor[] data, string message = null, int? first_n = null, int? summarize = null, string name = "Print")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["data"] = data;
            if (message != null)
                dict["message"] = message;
            if (first_n.HasValue)
                dict["first_n"] = first_n.Value;
            if (summarize.HasValue)
                dict["summarize"] = summarize.Value;
            var op = _op_def_lib._apply_op_helper("Print", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A queue that produces elements sorted by the first component value.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'PriorityQueue'.
        /// </param>
        /// <param name="shapes">
        ///    Optional argument
        ///    The shape of each component in a value. The length of this attr must
        ///    be either 0 or the same as the length of component_types. If the length of
        ///    this attr is 0, the shapes of queue elements are not constrained, and
        ///    only one element may be dequeued at a time.
        /// </param>
        /// <param name="component_types">
        ///    The type of each component in a value.
        /// </param>
        /// <param name="capacity">
        ///    The upper bound on the number of elements in this queue.
        ///    Negative numbers mean no limit.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this queue is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this queue will be shared under the given name
        ///    across multiple sessions.
        /// </param>
        /// <returns>
        ///    The handle to the queue.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Note that the PriorityQueue requires the first component of any element
        ///    to be a scalar int64, in addition to the other elements declared by
        ///    component_types.  Therefore calls to Enqueue and EnqueueMany (resp. Dequeue
        ///    and DequeueMany) on a PriorityQueue will all require (resp. output) one extra
        ///    entry in their input (resp. output) lists.
        /// </remarks>
        public static Tensor priority_queue (TensorShape[] shapes, TF_DataType[] component_types = null, int? capacity = null, string container = null, string shared_name = null, string name = "PriorityQueue")
        {
            var dict = new Dictionary<string, object>();
            dict["shapes"] = shapes;
            if (component_types != null)
                dict["component_types"] = component_types;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("PriorityQueue", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A queue that produces elements sorted by the first component value.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'PriorityQueueV2'.
        /// </param>
        /// <param name="shapes">
        ///    Optional argument
        ///    The shape of each component in a value. The length of this attr must
        ///    be either 0 or the same as the length of component_types. If the length of
        ///    this attr is 0, the shapes of queue elements are not constrained, and
        ///    only one element may be dequeued at a time.
        /// </param>
        /// <param name="component_types">
        ///    The type of each component in a value.
        /// </param>
        /// <param name="capacity">
        ///    The upper bound on the number of elements in this queue.
        ///    Negative numbers mean no limit.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this queue is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this queue will be shared under the given name
        ///    across multiple sessions.
        /// </param>
        /// <returns>
        ///    The handle to the queue.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Note that the PriorityQueue requires the first component of any element
        ///    to be a scalar int64, in addition to the other elements declared by
        ///    component_types.  Therefore calls to Enqueue and EnqueueMany (resp. Dequeue
        ///    and DequeueMany) on a PriorityQueue will all require (resp. output) one extra
        ///    entry in their input (resp. output) lists.
        /// </remarks>
        public static Tensor priority_queue_v2 (TensorShape[] shapes, TF_DataType[] component_types = null, int? capacity = null, string container = null, string shared_name = null, string name = "PriorityQueueV2")
        {
            var dict = new Dictionary<string, object>();
            dict["shapes"] = shapes;
            if (component_types != null)
                dict["component_types"] = component_types;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("PriorityQueueV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the product of elements across dimensions of a tensor.
        /// </summary>
        /// <param name="input">
        ///    The tensor to reduce.
        /// </param>
        /// <param name="reduction_indices">
        ///    The dimensions to reduce. Must be in the range
        ///    <c>[-rank(input), rank(input))</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Prod'.
        /// </param>
        /// <param name="keep_dims">
        ///    If true, retain reduced dimensions with length 1.
        /// </param>
        /// <returns>
        ///    The reduced tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Reduces <c>input</c> along the dimensions given in <c>axis</c>. Unless
        ///    <c>keep_dims</c> is true, the rank of the tensor is reduced by 1 for each entry in
        ///    <c>axis</c>. If <c>keep_dims</c> is true, the reduced dimensions are
        ///    retained with length 1.
        /// </remarks>
        public static Tensor prod (Tensor input, Tensor reduction_indices, bool? keep_dims = null, string name = "Prod")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["reduction_indices"] = reduction_indices;
            if (keep_dims.HasValue)
                dict["keep_dims"] = keep_dims.Value;
            var op = _op_def_lib._apply_op_helper("Prod", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the QR decompositions of one or more matrices.
        /// </summary>
        /// <param name="input">
        ///    A tensor of shape <c>[..., M, N]</c> whose inner-most 2 dimensions
        ///    form matrices of size <c>[M, N]</c>. Let <c>P</c> be the minimum of <c>M</c> and <c>N</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Qr'.
        /// </param>
        /// <param name="full_matrices">
        ///    If true, compute full-sized <c>q</c> and <c>r</c>. If false
        ///    (the default), compute only the leading <c>P</c> columns of <c>q</c>.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    q : Orthonormal basis for range of <c>a</c>. If <c>full_matrices</c> is <c>False</c> then
        ///    shape is <c>[..., M, P]</c>; if <c>full_matrices</c> is <c>True</c> then shape is
        ///    <c>[..., M, M]</c>.
        ///    r : Triangular factor. If <c>full_matrices</c> is <c>False</c> then shape is
        ///    <c>[..., P, N]</c>. If <c>full_matrices</c> is <c>True</c> then shape is <c>[..., M, N]</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Computes the QR decomposition of each inner matrix in <c>tensor</c> such that
        ///    <c>tensor[..., :, :] = q[..., :, :] * r[..., :,:])</c>
        ///    
        ///   <code>
        ///    # a is a tensor.
        ///    # q is a tensor of orthonormal matrices.
        ///    # r is a tensor of upper triangular matrices.
        ///    q, r = qr(a)
        ///    q_full, r_full = qr(a, full_matrices=True)
        ///   </code>
        /// </remarks>
        public static (Tensor q, Tensor r) qr (Tensor input, bool? full_matrices = null, string name = "Qr")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (full_matrices.HasValue)
                dict["full_matrices"] = full_matrices.Value;
            var op = _op_def_lib._apply_op_helper("Qr", name: name, keywords: dict);
            int _idx = 0;
            var q = op.outputs[_idx++];
            var r = op.outputs[_idx++];
            return (q, r);
        }

        /// <summary>
        ///    Use QuantizeAndDequantizeV2 instead.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QuantizeAndDequantize'.
        /// </param>
        /// <param name="signed_input">
        /// </param>
        /// <param name="num_bits">
        /// </param>
        /// <param name="range_given">
        /// </param>
        /// <param name="input_min">
        /// </param>
        /// <param name="input_max">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor quantize_and_dequantize (Tensor input, bool? signed_input = null, int? num_bits = null, bool? range_given = null, float? input_min = null, float? input_max = null, string name = "QuantizeAndDequantize")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (signed_input.HasValue)
                dict["signed_input"] = signed_input.Value;
            if (num_bits.HasValue)
                dict["num_bits"] = num_bits.Value;
            if (range_given.HasValue)
                dict["range_given"] = range_given.Value;
            if (input_min.HasValue)
                dict["input_min"] = input_min.Value;
            if (input_max.HasValue)
                dict["input_max"] = input_max.Value;
            var op = _op_def_lib._apply_op_helper("QuantizeAndDequantize", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Quantizes then dequantizes a tensor.
        /// </summary>
        /// <param name="input">
        ///    Tensor to quantize and then dequantize.
        /// </param>
        /// <param name="input_min">
        ///    If <c>range_given == True</c>, this specifies the minimum input value that needs to
        ///    be represented, otherwise it is determined from the min value of the <c>input</c>
        ///    tensor.
        /// </param>
        /// <param name="input_max">
        ///    If <c>range_given == True</c>, this specifies the maximum input value that needs to
        ///    be represented, otherwise it is determined from the max value of the <c>input</c>
        ///    tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QuantizeAndDequantizeV2'.
        /// </param>
        /// <param name="signed_input">
        ///    Whether the quantization is signed or unsigned. (actually this parameter should
        ///    have been called &amp;lt;b&amp;gt;<c>signed_output</c>&amp;lt;/b&amp;gt;)
        /// </param>
        /// <param name="num_bits">
        ///    The bitwidth of the quantization.
        /// </param>
        /// <param name="range_given">
        ///    Whether the range is given or should be determined from the <c>input</c> tensor.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op simulates the precision loss from the quantized forward pass by:
        ///    
        ///    1. Quantizing the tensor to fixed point numbers, which should match the target
        ///    quantization method when it is used in inference.
        ///    2. Dequantizing it back to floating point numbers for the following ops, most
        ///    likely matmul.
        ///    
        ///    There are different ways to quantize. This version uses only scaling, so 0.0
        ///    maps to 0.
        ///    
        ///    From the specified 'num_bits' in the quantized output type, it determines
        ///    minimum and maximum representable quantized values.
        ///    
        ///    e.g.
        ///    
        ///    *   [-128, 127] for signed, num_bits = 8, or
        ///    *   [0, 255] for unsigned, num_bits = 8.
        ///    
        ///    If range_given == False, the initial input_min, input_max will be determined
        ///    automatically as the minimum and maximum values in the input tensor, otherwise
        ///    the specified values of input_min, input_max are used.
        ///    
        ///    Note: If the input_min, input_max are specified, they do not need to equal the
        ///    actual minimum and maximum values in the tensor. e.g. in some cases it may be
        ///    beneficial to specify these values such that the low probability extremes of the
        ///    input distribution are clipped.
        ///    
        ///    This op determines the maximum scale_factor that would map the initial
        ///    [input_min, input_max] range to a range that lies within the representable
        ///    quantized range.
        ///    
        ///    It determines the scale from one of input_min and input_max, then updates the
        ///    other one to maximize the respresentable range.
        ///    
        ///    e.g.
        ///    
        ///    *   if the output is signed, num_bits = 8, [input_min, input_max] = [-10.0,
        ///    5.0]: it would use a scale_factor of -128 / -10.0 = 12.8 In this case, it
        ///    would update input_max to be 127 / 12.8 = 9.921875
        ///    *   if the output is signed, num_bits = 8, [input_min, input_max] = [-10.0,
        ///    10.0]: it would use a scale_factor of 127 / 10.0 = 12.7 In this case, it
        ///    would update input_min to be 128.0 / 12.7 = -10.07874
        ///    *   if the output is unsigned, input_min is forced to be 0, and only the
        ///    specified input_max is used.
        ///    
        ///    After determining the scale_factor and updating the input range, it applies the
        ///    following to each value in the 'input' tensor.
        ///    
        ///    output = round(clamp(value, input_min, input_max) * scale_factor) / scale_factor.
        ///    
        /// </remarks>
        public static Tensor quantize_and_dequantize_v2 (Tensor input, Tensor input_min, Tensor input_max, bool? signed_input = null, int? num_bits = null, bool? range_given = null, string name = "QuantizeAndDequantizeV2")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["input_min"] = input_min;
            dict["input_max"] = input_max;
            if (signed_input.HasValue)
                dict["signed_input"] = signed_input.Value;
            if (num_bits.HasValue)
                dict["num_bits"] = num_bits.Value;
            if (range_given.HasValue)
                dict["range_given"] = range_given.Value;
            var op = _op_def_lib._apply_op_helper("QuantizeAndDequantizeV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Quantizes then dequantizes a tensor.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="input_min">
        /// </param>
        /// <param name="input_max">
        /// </param>
        /// <param name="num_bits">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QuantizeAndDequantizeV3'.
        /// </param>
        /// <param name="signed_input">
        /// </param>
        /// <param name="range_given">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This is almost identical to QuantizeAndDequantizeV2, except that num_bits is a
        ///    tensor, so its value can change during training.
        /// </remarks>
        public static Tensor quantize_and_dequantize_v3 (Tensor input, Tensor input_min, Tensor input_max, Tensor num_bits, bool? signed_input = null, bool? range_given = null, string name = "QuantizeAndDequantizeV3")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["input_min"] = input_min;
            dict["input_max"] = input_max;
            dict["num_bits"] = num_bits;
            if (signed_input.HasValue)
                dict["signed_input"] = signed_input.Value;
            if (range_given.HasValue)
                dict["range_given"] = range_given.Value;
            var op = _op_def_lib._apply_op_helper("QuantizeAndDequantizeV3", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Convert the quantized 'input' tensor into a lower-precision 'output', using the
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="input_min">
        ///    The float value that the minimum quantized input value represents.
        /// </param>
        /// <param name="input_max">
        ///    The float value that the maximum quantized input value represents.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QuantizeDownAndShrinkRange'.
        /// </param>
        /// <param name="out_type">
        ///    Optional argument
        ///    The type of the output. Should be a lower bit depth than Tinput.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output :
        ///    output_min : The float value that the minimum quantized output value represents.
        ///    output_max : The float value that the maximum quantized output value represents.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    actual distribution of the values to maximize the usage of the lower bit depth
        ///    and adjusting the output min and max ranges accordingly.
        ///    
        ///    [input_min, input_max] are scalar floats that specify the range for the float
        ///    interpretation of the 'input' data. For example, if input_min is -1.0f and
        ///    input_max is 1.0f, and we are dealing with quint16 quantized data, then a 0
        ///    value in the 16-bit data should be interpreted as -1.0f, and a 65535 means 1.0f.
        ///    
        ///    This operator tries to squeeze as much precision as possible into an output with
        ///    a lower bit depth by calculating the actual min and max values found in the
        ///    data. For example, maybe that quint16 input has no values lower than 16,384 and
        ///    none higher than 49,152. That means only half the range is actually needed, all
        ///    the float interpretations are between -0.5f and 0.5f, so if we want to compress
        ///    the data into a quint8 output, we can use that range rather than the theoretical
        ///    -1.0f to 1.0f that is suggested by the input min and max.
        ///    
        ///    In practice, this is most useful for taking output from operations like
        ///    QuantizedMatMul that can produce higher bit-depth outputs than their inputs and
        ///    may have large potential output ranges, but in practice have a distribution of
        ///    input values that only uses a small fraction of the possible range. By feeding
        ///    that output into this operator, we can reduce it from 32 bits down to 8 with
        ///    minimal loss of accuracy.
        /// </remarks>
        public static (Tensor output, Tensor output_min, Tensor output_max) quantize_down_and_shrink_range (Tensor input, Tensor input_min, Tensor input_max, TF_DataType out_type, string name = "QuantizeDownAndShrinkRange")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["input_min"] = input_min;
            dict["input_max"] = input_max;
            dict["out_type"] = out_type;
            var op = _op_def_lib._apply_op_helper("QuantizeDownAndShrinkRange", name: name, keywords: dict);
            int _idx = 0;
            var output = op.outputs[_idx++];
            var output_min = op.outputs[_idx++];
            var output_max = op.outputs[_idx++];
            return (output, output_min, output_max);
        }

        /// <summary>
        ///    Quantize the 'input' tensor of type float to 'output' tensor of type 'T'.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="min_range">
        ///    The minimum scalar value possibly produced for the input.
        /// </param>
        /// <param name="max_range">
        ///    The maximum scalar value possibly produced for the input.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QuantizeV2'.
        /// </param>
        /// <param name="T">
        ///    Optional argument
        /// </param>
        /// <param name="mode">
        /// </param>
        /// <param name="round_mode">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output : The quantized data produced from the float input.
        ///    output_min : The actual minimum scalar value used for the output.
        ///    output_max : The actual maximum scalar value used for the output.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    [min_range, max_range] are scalar floats that specify the range for
        ///    the 'input' data. The 'mode' attribute controls exactly which calculations are
        ///    used to convert the float values to their quantized equivalents.  The
        ///    'round_mode' attribute controls which rounding tie-breaking algorithm is used
        ///    when rounding float values to their quantized equivalents.
        ///    
        ///    In 'MIN_COMBINED' mode, each value of the tensor will undergo the following:
        ///    
        ///   <code>
        ///    out[i] = (in[i] - min_range) * range(T) / (max_range - min_range)
        ///    if T == qint8, out[i] -= (range(T) + 1) / 2.0
        ///   </code>
        ///    
        ///    here <c>range(T) = numeric_limits&amp;lt;T&amp;gt;::max() - numeric_limits&amp;lt;T&amp;gt;::min()</c>
        ///    
        ///    *MIN_COMBINED Mode Example*
        ///    
        ///    Assume the input is type float and has a possible range of [0.0, 6.0] and the
        ///    output type is quint8 ([0, 255]). The min_range and max_range values should be
        ///    specified as 0.0 and 6.0. Quantizing from float to quint8 will multiply each
        ///    value of the input by 255/6 and cast to quint8.
        ///    
        ///    If the output type was qint8 ([-128, 127]), the operation will additionally
        ///    subtract each value by 128 prior to casting, so that the range of values aligns
        ///    with the range of qint8.
        ///    
        ///    If the mode is 'MIN_FIRST', then this approach is used:
        ///    
        ///   <code>
        ///    num_discrete_values = 1 &amp;lt;&amp;lt; (# of bits in T)
        ///    range_adjust = num_discrete_values / (num_discrete_values - 1)
        ///    range = (range_max - range_min) * range_adjust
        ///    range_scale = num_discrete_values / range
        ///    quantized = round(input * range_scale) - round(range_min * range_scale) +
        ///    numeric_limits&amp;lt;T&amp;gt;::min()
        ///    quantized = max(quantized, numeric_limits&amp;lt;T&amp;gt;::min())
        ///    quantized = min(quantized, numeric_limits&amp;lt;T&amp;gt;::max())
        ///   </code>
        ///    
        ///    The biggest difference between this and MIN_COMBINED is that the minimum range
        ///    is rounded first, before it's subtracted from the rounded value. With
        ///    MIN_COMBINED, a small bias is introduced where repeated iterations of quantizing
        ///    and dequantizing will introduce a larger and larger error.
        ///    
        ///    *SCALED mode Example*
        ///    
        ///    <c>SCALED</c> mode matches the quantization approach used in
        ///    <c>QuantizeAndDequantize{V2|V3}</c>.
        ///    
        ///    If the mode is <c>SCALED</c>, we do not use the full range of the output type,
        ///    choosing to elide the lowest possible value for symmetry (e.g., output range is
        ///    -127 to 127, not -128 to 127 for signed 8 bit quantization), so that 0.0 maps to
        ///    0.
        ///    
        ///    We first find the range of values in our tensor. The
        ///    range we use is always centered on 0, so we find m such that
        ///    
        ///   <code>
        ///    m = max(abs(input_min), abs(input_max))
        ///   </code>
        ///    
        ///    Our input tensor range is then <c>[-m, m]</c>.
        ///    
        ///    Next, we choose our fixed-point quantization buckets, <c>[min_fixed, max_fixed]</c>.
        ///    If T is signed, this is
        ///    
        ///   <code>
        ///    num_bits = sizeof(T) * 8
        ///    [min_fixed, max_fixed] =
        ///    [-(1 &amp;lt;&amp;lt; (num_bits - 1) - 1), (1 &amp;lt;&amp;lt; (num_bits - 1)) - 1]
        ///   </code>
        ///    
        ///    Otherwise, if T is unsigned, the fixed-point range is
        ///    
        ///   <code>
        ///    [min_fixed, max_fixed] = [0, (1 &amp;lt;&amp;lt; num_bits) - 1]
        ///   </code>
        ///    
        ///    From this we compute our scaling factor, s:
        ///    
        ///   <code>
        ///    s = (max_fixed - min_fixed) / (2 * m)
        ///   </code>
        ///    
        ///    Now we can quantize the elements of our tensor:
        ///    
        ///   <code>
        ///    result = round(input * s)
        ///   </code>
        ///    
        ///    One thing to watch out for is that the operator may choose to adjust the
        ///    requested minimum and maximum values slightly during the quantization process,
        ///    so you should always use the output ports as the range for further calculations.
        ///    For example, if the requested minimum and maximum values are close to equal,
        ///    they will be separated by a small epsilon value to prevent ill-formed quantized
        ///    buffers from being created. Otherwise, you can end up with buffers where all the
        ///    quantized values map to the same float value, which causes problems for
        ///    operations that have to perform further calculations on them.
        /// </remarks>
        public static (Tensor output, Tensor output_min, Tensor output_max) quantize_v2 (Tensor input, Tensor min_range, Tensor max_range, TF_DataType T, string mode = null, string round_mode = null, string name = "QuantizeV2")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["min_range"] = min_range;
            dict["max_range"] = max_range;
            dict["T"] = T;
            if (mode != null)
                dict["mode"] = mode;
            if (round_mode != null)
                dict["round_mode"] = round_mode;
            var op = _op_def_lib._apply_op_helper("QuantizeV2", name: name, keywords: dict);
            int _idx = 0;
            var output = op.outputs[_idx++];
            var output_min = op.outputs[_idx++];
            var output_max = op.outputs[_idx++];
            return (output, output_min, output_max);
        }

        /// <summary>
        ///    Returns x + y element-wise, working on quantized buffers.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="min_x">
        ///    The float value that the lowest quantized <c>x</c> value represents.
        /// </param>
        /// <param name="max_x">
        ///    The float value that the highest quantized <c>x</c> value represents.
        /// </param>
        /// <param name="min_y">
        ///    The float value that the lowest quantized <c>y</c> value represents.
        /// </param>
        /// <param name="max_y">
        ///    The float value that the highest quantized <c>y</c> value represents.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QuantizedAdd'.
        /// </param>
        /// <param name="Toutput">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    z :
        ///    min_z : The float value that the lowest quantized output value represents.
        ///    max_z : The float value that the highest quantized output value represents.
        ///    
        ///    *NOTE*: <c>QuantizedAdd</c> supports limited forms of broadcasting. More about
        ///    broadcasting [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor z, Tensor min_z, Tensor max_z) quantized_add (Tensor x, Tensor y, Tensor min_x, Tensor max_x, Tensor min_y, Tensor max_y, TF_DataType? Toutput = null, string name = "QuantizedAdd")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            dict["min_x"] = min_x;
            dict["max_x"] = max_x;
            dict["min_y"] = min_y;
            dict["max_y"] = max_y;
            if (Toutput.HasValue)
                dict["Toutput"] = Toutput.Value;
            var op = _op_def_lib._apply_op_helper("QuantizedAdd", name: name, keywords: dict);
            int _idx = 0;
            var z = op.outputs[_idx++];
            var min_z = op.outputs[_idx++];
            var max_z = op.outputs[_idx++];
            return (z, min_z, max_z);
        }

        /// <summary>
        ///    Produces the average pool of the input tensor for quantized types.
        /// </summary>
        /// <param name="input">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.
        /// </param>
        /// <param name="min_input">
        ///    The float value that the lowest quantized input value represents.
        /// </param>
        /// <param name="max_input">
        ///    The float value that the highest quantized input value represents.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QuantizedAvgPool'.
        /// </param>
        /// <param name="ksize">
        ///    Optional argument
        ///    The size of the window for each dimension of the input tensor.
        ///    The length must be 4 to match the number of dimensions of the input.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    The stride of the sliding window for each dimension of the input
        ///    tensor.  The length must be 4 to match the number of dimensions of the input.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output :
        ///    min_output : The float value that the lowest quantized output value represents.
        ///    max_output : The float value that the highest quantized output value represents.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor output, Tensor min_output, Tensor max_output) quantized_avg_pool (Tensor input, Tensor min_input, Tensor max_input, int[] ksize, int[] strides, string padding, string name = "QuantizedAvgPool")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["min_input"] = min_input;
            dict["max_input"] = max_input;
            dict["ksize"] = ksize;
            dict["strides"] = strides;
            dict["padding"] = padding;
            var op = _op_def_lib._apply_op_helper("QuantizedAvgPool", name: name, keywords: dict);
            int _idx = 0;
            var output = op.outputs[_idx++];
            var min_output = op.outputs[_idx++];
            var max_output = op.outputs[_idx++];
            return (output, min_output, max_output);
        }

        /// <summary>
        ///    Quantized Batch normalization.
        /// </summary>
        /// <param name="t">
        ///    A 4D input Tensor.
        /// </param>
        /// <param name="t_min">
        ///    The value represented by the lowest quantized input.
        /// </param>
        /// <param name="t_max">
        ///    The value represented by the highest quantized input.
        /// </param>
        /// <param name="m">
        ///    A 1D mean Tensor with size matching the last dimension of t.
        ///    This is the first output from tf.nn.moments,
        ///    or a saved moving average thereof.
        /// </param>
        /// <param name="m_min">
        ///    The value represented by the lowest quantized mean.
        /// </param>
        /// <param name="m_max">
        ///    The value represented by the highest quantized mean.
        /// </param>
        /// <param name="v">
        ///    A 1D variance Tensor with size matching the last dimension of t.
        ///    This is the second output from tf.nn.moments,
        ///    or a saved moving average thereof.
        /// </param>
        /// <param name="v_min">
        ///    The value represented by the lowest quantized variance.
        /// </param>
        /// <param name="v_max">
        ///    The value represented by the highest quantized variance.
        /// </param>
        /// <param name="beta">
        ///    A 1D beta Tensor with size matching the last dimension of t.
        ///    An offset to be added to the normalized tensor.
        /// </param>
        /// <param name="beta_min">
        ///    The value represented by the lowest quantized offset.
        /// </param>
        /// <param name="beta_max">
        ///    The value represented by the highest quantized offset.
        /// </param>
        /// <param name="gamma">
        ///    A 1D gamma Tensor with size matching the last dimension of t.
        ///    If "scale_after_normalization" is true, this tensor will be multiplied
        ///    with the normalized tensor.
        /// </param>
        /// <param name="gamma_min">
        ///    The value represented by the lowest quantized gamma.
        /// </param>
        /// <param name="gamma_max">
        ///    The value represented by the highest quantized gamma.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QuantizedBatchNormWithGlobalNormalization'.
        /// </param>
        /// <param name="out_type">
        ///    Optional argument
        /// </param>
        /// <param name="variance_epsilon">
        ///    Optional argument
        ///    A small float number to avoid dividing by 0.
        /// </param>
        /// <param name="scale_after_normalization">
        ///    Optional argument
        ///    A bool indicating whether the resulted tensor
        ///    needs to be multiplied with gamma.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    result :
        ///    result_min :
        ///    result_max :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    This op is deprecated and will be removed in the future. Prefer
        ///    <c>tf.nn.batch_normalization</c>.
        /// </remarks>
        public static (Tensor result, Tensor result_min, Tensor result_max) quantized_batch_norm_with_global_normalization (Tensor t, Tensor t_min, Tensor t_max, Tensor m, Tensor m_min, Tensor m_max, Tensor v, Tensor v_min, Tensor v_max, Tensor beta, Tensor beta_min, Tensor beta_max, Tensor gamma, Tensor gamma_min, Tensor gamma_max, TF_DataType out_type, float variance_epsilon, bool scale_after_normalization, string name = "QuantizedBatchNormWithGlobalNormalization")
        {
            var dict = new Dictionary<string, object>();
            dict["t"] = t;
            dict["t_min"] = t_min;
            dict["t_max"] = t_max;
            dict["m"] = m;
            dict["m_min"] = m_min;
            dict["m_max"] = m_max;
            dict["v"] = v;
            dict["v_min"] = v_min;
            dict["v_max"] = v_max;
            dict["beta"] = beta;
            dict["beta_min"] = beta_min;
            dict["beta_max"] = beta_max;
            dict["gamma"] = gamma;
            dict["gamma_min"] = gamma_min;
            dict["gamma_max"] = gamma_max;
            dict["out_type"] = out_type;
            dict["variance_epsilon"] = variance_epsilon;
            dict["scale_after_normalization"] = scale_after_normalization;
            var op = _op_def_lib._apply_op_helper("QuantizedBatchNormWithGlobalNormalization", name: name, keywords: dict);
            int _idx = 0;
            var result = op.outputs[_idx++];
            var result_min = op.outputs[_idx++];
            var result_max = op.outputs[_idx++];
            return (result, result_min, result_max);
        }

        /// <summary>
        ///    Adds Tensor 'bias' to Tensor 'input' for Quantized types.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="bias">
        ///    A 1D bias Tensor with size matching the last dimension of 'input'.
        /// </param>
        /// <param name="min_input">
        ///    The float value that the lowest quantized input value represents.
        /// </param>
        /// <param name="max_input">
        ///    The float value that the highest quantized input value represents.
        /// </param>
        /// <param name="min_bias">
        ///    The float value that the lowest quantized bias value represents.
        /// </param>
        /// <param name="max_bias">
        ///    The float value that the highest quantized bias value represents.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QuantizedBiasAdd'.
        /// </param>
        /// <param name="out_type">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output :
        ///    min_out : The float value that the lowest quantized output value represents.
        ///    max_out : The float value that the highest quantized output value represents.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Broadcasts the values of bias on dimensions 0..N-2 of 'input'.
        /// </remarks>
        public static (Tensor output, Tensor min_out, Tensor max_out) quantized_bias_add (Tensor input, Tensor bias, Tensor min_input, Tensor max_input, Tensor min_bias, Tensor max_bias, TF_DataType out_type, string name = "QuantizedBiasAdd")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["bias"] = bias;
            dict["min_input"] = min_input;
            dict["max_input"] = max_input;
            dict["min_bias"] = min_bias;
            dict["max_bias"] = max_bias;
            dict["out_type"] = out_type;
            var op = _op_def_lib._apply_op_helper("QuantizedBiasAdd", name: name, keywords: dict);
            int _idx = 0;
            var output = op.outputs[_idx++];
            var min_out = op.outputs[_idx++];
            var max_out = op.outputs[_idx++];
            return (output, min_out, max_out);
        }

        /// <summary>
        ///    Concatenates quantized tensors along one dimension.
        /// </summary>
        /// <param name="concat_dim">
        ///    0-D.  The dimension along which to concatenate.  Must be in the
        ///    range [0, rank(values)).
        /// </param>
        /// <param name="values">
        ///    The <c>N</c> Tensors to concatenate. Their ranks and types must match,
        ///    and their sizes must match in all dimensions except <c>concat_dim</c>.
        /// </param>
        /// <param name="input_mins">
        ///    The minimum scalar values for each of the input tensors.
        /// </param>
        /// <param name="input_maxes">
        ///    The maximum scalar values for each of the input tensors.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QuantizedConcat'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output : A <c>Tensor</c> with the concatenation of values stacked along the
        ///    <c>concat_dim</c> dimension.  This tensor's shape matches that of <c>values</c> except
        ///    in <c>concat_dim</c> where it has the sum of the sizes.
        ///    output_min : The float value that the minimum quantized output value represents.
        ///    output_max : The float value that the maximum quantized output value represents.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor output, Tensor output_min, Tensor output_max) quantized_concat (Tensor concat_dim, Tensor[] values, Tensor[] input_mins, Tensor[] input_maxes, string name = "QuantizedConcat")
        {
            var dict = new Dictionary<string, object>();
            dict["concat_dim"] = concat_dim;
            dict["values"] = values;
            dict["input_mins"] = input_mins;
            dict["input_maxes"] = input_maxes;
            var op = _op_def_lib._apply_op_helper("QuantizedConcat", name: name, keywords: dict);
            int _idx = 0;
            var output = op.outputs[_idx++];
            var output_min = op.outputs[_idx++];
            var output_max = op.outputs[_idx++];
            return (output, output_min, output_max);
        }

        /// <summary>
        ///    Computes a 2D convolution given quantized 4D input and filter tensors.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="filter">
        ///    filter's input_depth dimension must match input's depth dimensions.
        /// </param>
        /// <param name="min_input">
        ///    The float value that the lowest quantized input value represents.
        /// </param>
        /// <param name="max_input">
        ///    The float value that the highest quantized input value represents.
        /// </param>
        /// <param name="min_filter">
        ///    The float value that the lowest quantized filter value represents.
        /// </param>
        /// <param name="max_filter">
        ///    The float value that the highest quantized filter value represents.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QuantizedConv2D'.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    The stride of the sliding window for each dimension of the input
        ///    tensor.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <param name="out_type">
        /// </param>
        /// <param name="dilations">
        ///    1-D tensor of length 4.  The dilation factor for each dimension of
        ///    <c>input</c>. If set to k &amp;gt; 1, there will be k-1 skipped cells between each
        ///    filter element on that dimension. The dimension order is determined by the
        ///    value of <c>data_format</c>, see above for details. Dilations in the batch and
        ///    depth dimensions must be 1.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output :
        ///    min_output : The float value that the lowest quantized output value represents.
        ///    max_output : The float value that the highest quantized output value represents.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    The inputs are quantized tensors where the lowest value represents the real
        ///    number of the associated minimum, and the highest represents the maximum.
        ///    This means that you can only interpret the quantized output in the same way, by
        ///    taking the returned minimum and maximum values into account.
        /// </remarks>
        public static (Tensor output, Tensor min_output, Tensor max_output) quantized_conv2d (Tensor input, Tensor filter, Tensor min_input, Tensor max_input, Tensor min_filter, Tensor max_filter, int[] strides, string padding, TF_DataType? out_type = null, int[] dilations = null, string name = "QuantizedConv2D")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["filter"] = filter;
            dict["min_input"] = min_input;
            dict["max_input"] = max_input;
            dict["min_filter"] = min_filter;
            dict["max_filter"] = max_filter;
            dict["strides"] = strides;
            dict["padding"] = padding;
            if (out_type.HasValue)
                dict["out_type"] = out_type.Value;
            if (dilations != null)
                dict["dilations"] = dilations;
            var op = _op_def_lib._apply_op_helper("QuantizedConv2D", name: name, keywords: dict);
            int _idx = 0;
            var output = op.outputs[_idx++];
            var min_output = op.outputs[_idx++];
            var max_output = op.outputs[_idx++];
            return (output, min_output, max_output);
        }

        /// <summary>
        ///    Quantized Instance normalization.
        /// </summary>
        /// <param name="x">
        ///    A 4D input Tensor.
        /// </param>
        /// <param name="x_min">
        ///    The value represented by the lowest quantized input.
        /// </param>
        /// <param name="x_max">
        ///    The value represented by the highest quantized input.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QuantizedInstanceNorm'.
        /// </param>
        /// <param name="output_range_given">
        ///    If True, <c>given_y_min</c> and <c>given_y_min</c>
        ///    and <c>given_y_max</c> are used as the output range. Otherwise,
        ///    the implementation computes the output range.
        /// </param>
        /// <param name="given_y_min">
        ///    Output in <c>y_min</c> if <c>output_range_given</c> is True.
        /// </param>
        /// <param name="given_y_max">
        ///    Output in <c>y_max</c> if <c>output_range_given</c> is True.
        /// </param>
        /// <param name="variance_epsilon">
        ///    A small float number to avoid dividing by 0.
        /// </param>
        /// <param name="min_separation">
        ///    Minimum value of <c>y_max - y_min</c>
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    y : A 4D Tensor.
        ///    y_min : The value represented by the lowest quantized output.
        ///    y_max : The value represented by the highest quantized output.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor y, Tensor y_min, Tensor y_max) quantized_instance_norm (Tensor x, Tensor x_min, Tensor x_max, bool? output_range_given = null, float? given_y_min = null, float? given_y_max = null, float? variance_epsilon = null, float? min_separation = null, string name = "QuantizedInstanceNorm")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["x_min"] = x_min;
            dict["x_max"] = x_max;
            if (output_range_given.HasValue)
                dict["output_range_given"] = output_range_given.Value;
            if (given_y_min.HasValue)
                dict["given_y_min"] = given_y_min.Value;
            if (given_y_max.HasValue)
                dict["given_y_max"] = given_y_max.Value;
            if (variance_epsilon.HasValue)
                dict["variance_epsilon"] = variance_epsilon.Value;
            if (min_separation.HasValue)
                dict["min_separation"] = min_separation.Value;
            var op = _op_def_lib._apply_op_helper("QuantizedInstanceNorm", name: name, keywords: dict);
            int _idx = 0;
            var y = op.outputs[_idx++];
            var y_min = op.outputs[_idx++];
            var y_max = op.outputs[_idx++];
            return (y, y_min, y_max);
        }

        /// <summary>
        ///    Perform a quantized matrix multiplication of  <c>a</c> by the matrix <c>b</c>.
        /// </summary>
        /// <param name="a">
        ///    Must be a two-dimensional tensor.
        /// </param>
        /// <param name="b">
        ///    Must be a two-dimensional tensor.
        /// </param>
        /// <param name="min_a">
        ///    The float value that the lowest quantized <c>a</c> value represents.
        /// </param>
        /// <param name="max_a">
        ///    The float value that the highest quantized <c>a</c> value represents.
        /// </param>
        /// <param name="min_b">
        ///    The float value that the lowest quantized <c>b</c> value represents.
        /// </param>
        /// <param name="max_b">
        ///    The float value that the highest quantized <c>b</c> value represents.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QuantizedMatMul'.
        /// </param>
        /// <param name="Toutput">
        /// </param>
        /// <param name="transpose_a">
        ///    If true, <c>a</c> is transposed before multiplication.
        /// </param>
        /// <param name="transpose_b">
        ///    If true, <c>b</c> is transposed before multiplication.
        /// </param>
        /// <param name="Tactivation">
        ///    The type of output produced by activation function
        ///    following this operation.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output :
        ///    min_out : The float value that the lowest quantized output value represents.
        ///    max_out : The float value that the highest quantized output value represents.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    The inputs must be two-dimensional matrices and the inner dimension of
        ///    <c>a</c> (after being transposed if <c>transpose_a</c> is non-zero) must match the
        ///    outer dimension of <c>b</c> (after being transposed if <c>transposed_b</c> is
        ///    non-zero).
        /// </remarks>
        public static (Tensor output, Tensor min_out, Tensor max_out) quantized_mat_mul (Tensor a, Tensor b, Tensor min_a, Tensor max_a, Tensor min_b, Tensor max_b, TF_DataType? Toutput = null, bool? transpose_a = null, bool? transpose_b = null, TF_DataType? Tactivation = null, string name = "QuantizedMatMul")
        {
            var dict = new Dictionary<string, object>();
            dict["a"] = a;
            dict["b"] = b;
            dict["min_a"] = min_a;
            dict["max_a"] = max_a;
            dict["min_b"] = min_b;
            dict["max_b"] = max_b;
            if (Toutput.HasValue)
                dict["Toutput"] = Toutput.Value;
            if (transpose_a.HasValue)
                dict["transpose_a"] = transpose_a.Value;
            if (transpose_b.HasValue)
                dict["transpose_b"] = transpose_b.Value;
            if (Tactivation.HasValue)
                dict["Tactivation"] = Tactivation.Value;
            var op = _op_def_lib._apply_op_helper("QuantizedMatMul", name: name, keywords: dict);
            int _idx = 0;
            var output = op.outputs[_idx++];
            var min_out = op.outputs[_idx++];
            var max_out = op.outputs[_idx++];
            return (output, min_out, max_out);
        }

        /// <summary>
        ///    Produces the max pool of the input tensor for quantized types.
        /// </summary>
        /// <param name="input">
        ///    The 4D (batch x rows x cols x depth) Tensor to MaxReduce over.
        /// </param>
        /// <param name="min_input">
        ///    The float value that the lowest quantized input value represents.
        /// </param>
        /// <param name="max_input">
        ///    The float value that the highest quantized input value represents.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QuantizedMaxPool'.
        /// </param>
        /// <param name="ksize">
        ///    Optional argument
        ///    The size of the window for each dimension of the input tensor.
        ///    The length must be 4 to match the number of dimensions of the input.
        /// </param>
        /// <param name="strides">
        ///    Optional argument
        ///    The stride of the sliding window for each dimension of the input
        ///    tensor. The length must be 4 to match the number of dimensions of the input.
        /// </param>
        /// <param name="padding">
        ///    Optional argument
        ///    The type of padding algorithm to use.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output :
        ///    min_output : The float value that the lowest quantized output value represents.
        ///    max_output : The float value that the highest quantized output value represents.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor output, Tensor min_output, Tensor max_output) quantized_max_pool (Tensor input, Tensor min_input, Tensor max_input, int[] ksize, int[] strides, string padding, string name = "QuantizedMaxPool")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["min_input"] = min_input;
            dict["max_input"] = max_input;
            dict["ksize"] = ksize;
            dict["strides"] = strides;
            dict["padding"] = padding;
            var op = _op_def_lib._apply_op_helper("QuantizedMaxPool", name: name, keywords: dict);
            int _idx = 0;
            var output = op.outputs[_idx++];
            var min_output = op.outputs[_idx++];
            var max_output = op.outputs[_idx++];
            return (output, min_output, max_output);
        }

        /// <summary>
        ///    Returns x * y element-wise, working on quantized buffers.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="min_x">
        ///    The float value that the lowest quantized <c>x</c> value represents.
        /// </param>
        /// <param name="max_x">
        ///    The float value that the highest quantized <c>x</c> value represents.
        /// </param>
        /// <param name="min_y">
        ///    The float value that the lowest quantized <c>y</c> value represents.
        /// </param>
        /// <param name="max_y">
        ///    The float value that the highest quantized <c>y</c> value represents.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QuantizedMul'.
        /// </param>
        /// <param name="Toutput">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    z :
        ///    min_z : The float value that the lowest quantized output value represents.
        ///    max_z : The float value that the highest quantized output value represents.
        ///    
        ///    *NOTE*: <c>QuantizedMul</c> supports limited forms of broadcasting. More about
        ///    broadcasting [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor z, Tensor min_z, Tensor max_z) quantized_mul (Tensor x, Tensor y, Tensor min_x, Tensor max_x, Tensor min_y, Tensor max_y, TF_DataType? Toutput = null, string name = "QuantizedMul")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            dict["min_x"] = min_x;
            dict["max_x"] = max_x;
            dict["min_y"] = min_y;
            dict["max_y"] = max_y;
            if (Toutput.HasValue)
                dict["Toutput"] = Toutput.Value;
            var op = _op_def_lib._apply_op_helper("QuantizedMul", name: name, keywords: dict);
            int _idx = 0;
            var z = op.outputs[_idx++];
            var min_z = op.outputs[_idx++];
            var max_z = op.outputs[_idx++];
            return (z, min_z, max_z);
        }

        /// <summary>
        ///    Computes Quantized Rectified Linear: <c>max(features, 0)</c>
        /// </summary>
        /// <param name="features">
        /// </param>
        /// <param name="min_features">
        ///    The float value that the lowest quantized value represents.
        /// </param>
        /// <param name="max_features">
        ///    The float value that the highest quantized value represents.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QuantizedRelu'.
        /// </param>
        /// <param name="out_type">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    activations : Has the same output shape as "features".
        ///    min_activations : The float value that the lowest quantized value represents.
        ///    max_activations : The float value that the highest quantized value represents.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor activations, Tensor min_activations, Tensor max_activations) quantized_relu (Tensor features, Tensor min_features, Tensor max_features, TF_DataType? out_type = null, string name = "QuantizedRelu")
        {
            var dict = new Dictionary<string, object>();
            dict["features"] = features;
            dict["min_features"] = min_features;
            dict["max_features"] = max_features;
            if (out_type.HasValue)
                dict["out_type"] = out_type.Value;
            var op = _op_def_lib._apply_op_helper("QuantizedRelu", name: name, keywords: dict);
            int _idx = 0;
            var activations = op.outputs[_idx++];
            var min_activations = op.outputs[_idx++];
            var max_activations = op.outputs[_idx++];
            return (activations, min_activations, max_activations);
        }

        /// <summary>
        ///    Computes Quantized Rectified Linear 6: <c>min(max(features, 0), 6)</c>
        /// </summary>
        /// <param name="features">
        /// </param>
        /// <param name="min_features">
        ///    The float value that the lowest quantized value represents.
        /// </param>
        /// <param name="max_features">
        ///    The float value that the highest quantized value represents.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QuantizedRelu6'.
        /// </param>
        /// <param name="out_type">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    activations : Has the same output shape as "features".
        ///    min_activations : The float value that the lowest quantized value represents.
        ///    max_activations : The float value that the highest quantized value represents.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor activations, Tensor min_activations, Tensor max_activations) quantized_relu6 (Tensor features, Tensor min_features, Tensor max_features, TF_DataType? out_type = null, string name = "QuantizedRelu6")
        {
            var dict = new Dictionary<string, object>();
            dict["features"] = features;
            dict["min_features"] = min_features;
            dict["max_features"] = max_features;
            if (out_type.HasValue)
                dict["out_type"] = out_type.Value;
            var op = _op_def_lib._apply_op_helper("QuantizedRelu6", name: name, keywords: dict);
            int _idx = 0;
            var activations = op.outputs[_idx++];
            var min_activations = op.outputs[_idx++];
            var max_activations = op.outputs[_idx++];
            return (activations, min_activations, max_activations);
        }

        /// <summary>
        ///    Computes Quantized Rectified Linear X: <c>min(max(features, 0), max_value)</c>
        /// </summary>
        /// <param name="features">
        /// </param>
        /// <param name="max_value">
        /// </param>
        /// <param name="min_features">
        ///    The float value that the lowest quantized value represents.
        /// </param>
        /// <param name="max_features">
        ///    The float value that the highest quantized value represents.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QuantizedReluX'.
        /// </param>
        /// <param name="out_type">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    activations : Has the same output shape as "features".
        ///    min_activations : The float value that the lowest quantized value represents.
        ///    max_activations : The float value that the highest quantized value represents.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor activations, Tensor min_activations, Tensor max_activations) quantized_relu_x (Tensor features, Tensor max_value, Tensor min_features, Tensor max_features, TF_DataType? out_type = null, string name = "QuantizedReluX")
        {
            var dict = new Dictionary<string, object>();
            dict["features"] = features;
            dict["max_value"] = max_value;
            dict["min_features"] = min_features;
            dict["max_features"] = max_features;
            if (out_type.HasValue)
                dict["out_type"] = out_type.Value;
            var op = _op_def_lib._apply_op_helper("QuantizedReluX", name: name, keywords: dict);
            int _idx = 0;
            var activations = op.outputs[_idx++];
            var min_activations = op.outputs[_idx++];
            var max_activations = op.outputs[_idx++];
            return (activations, min_activations, max_activations);
        }

        /// <summary>
        ///    Reshapes a quantized tensor as per the Reshape op.
        /// </summary>
        /// <param name="tensor">
        /// </param>
        /// <param name="shape">
        ///    Defines the shape of the output tensor.
        /// </param>
        /// <param name="input_min">
        ///    The minimum value of the input.
        /// </param>
        /// <param name="input_max">
        ///    The maximum value of the input.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QuantizedReshape'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output :
        ///    output_min : This value is copied from input_min.
        ///    output_max : This value is copied from input_max.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///   <code>
        /// </remarks>
        public static (Tensor output, Tensor output_min, Tensor output_max) quantized_reshape (Tensor tensor, Tensor shape, Tensor input_min, Tensor input_max, string name = "QuantizedReshape")
        {
            var dict = new Dictionary<string, object>();
            dict["tensor"] = tensor;
            dict["shape"] = shape;
            dict["input_min"] = input_min;
            dict["input_max"] = input_max;
            var op = _op_def_lib._apply_op_helper("QuantizedReshape", name: name, keywords: dict);
            int _idx = 0;
            var output = op.outputs[_idx++];
            var output_min = op.outputs[_idx++];
            var output_max = op.outputs[_idx++];
            return (output, output_min, output_max);
        }

        /// <summary>
        ///    Resize quantized <c>images</c> to <c>size</c> using quantized bilinear interpolation.
        /// </summary>
        /// <param name="images">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.
        /// </param>
        /// <param name="size">
        ///    = A 1-D int32 Tensor of 2 elements: <c>new_height, new_width</c>.  The
        ///    new size for the images.
        /// </param>
        /// <param name="min">
        /// </param>
        /// <param name="max">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QuantizedResizeBilinear'.
        /// </param>
        /// <param name="align_corners">
        ///    If true, the centers of the 4 corner pixels of the input and output tensors are
        ///    aligned, preserving the values at the corner pixels. Defaults to false.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    resized_images : 4-D with shape
        ///    <c>[batch, new_height, new_width, channels]</c>.
        ///    out_min :
        ///    out_max :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Input images and output images must be quantized types.
        /// </remarks>
        public static (Tensor resized_images, Tensor out_min, Tensor out_max) quantized_resize_bilinear (Tensor images, Tensor size, Tensor min, Tensor max, bool? align_corners = null, string name = "QuantizedResizeBilinear")
        {
            var dict = new Dictionary<string, object>();
            dict["images"] = images;
            dict["size"] = size;
            dict["min"] = min;
            dict["max"] = max;
            if (align_corners.HasValue)
                dict["align_corners"] = align_corners.Value;
            var op = _op_def_lib._apply_op_helper("QuantizedResizeBilinear", name: name, keywords: dict);
            int _idx = 0;
            var resized_images = op.outputs[_idx++];
            var out_min = op.outputs[_idx++];
            var out_max = op.outputs[_idx++];
            return (resized_images, out_min, out_max);
        }

        /// <summary>
        ///    Closes the given queue.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a queue.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QueueClose'.
        /// </param>
        /// <param name="cancel_pending_enqueues">
        ///    If true, all pending enqueue requests that are
        ///    blocked on the given queue will be canceled.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    This operation signals that no more elements will be enqueued in the
        ///    given queue. Subsequent Enqueue(Many) operations will fail.
        ///    Subsequent Dequeue(Many) operations will continue to succeed if
        ///    sufficient elements remain in the queue. Subsequent Dequeue(Many)
        ///    operations that would block will fail immediately.
        /// </remarks>
        public static Operation queue_close (Tensor handle, bool? cancel_pending_enqueues = null, string name = "QueueClose")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            if (cancel_pending_enqueues.HasValue)
                dict["cancel_pending_enqueues"] = cancel_pending_enqueues.Value;
            var op = _op_def_lib._apply_op_helper("QueueClose", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Closes the given queue.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a queue.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QueueCloseV2'.
        /// </param>
        /// <param name="cancel_pending_enqueues">
        ///    If true, all pending enqueue requests that are
        ///    blocked on the given queue will be canceled.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    This operation signals that no more elements will be enqueued in the
        ///    given queue. Subsequent Enqueue(Many) operations will fail.
        ///    Subsequent Dequeue(Many) operations will continue to succeed if
        ///    sufficient elements remain in the queue. Subsequent Dequeue(Many)
        ///    operations that would block will fail immediately.
        /// </remarks>
        public static Operation queue_close_v2 (Tensor handle, bool? cancel_pending_enqueues = null, string name = "QueueCloseV2")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            if (cancel_pending_enqueues.HasValue)
                dict["cancel_pending_enqueues"] = cancel_pending_enqueues.Value;
            var op = _op_def_lib._apply_op_helper("QueueCloseV2", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Dequeues a tuple of one or more tensors from the given queue.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a queue.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QueueDequeue'.
        /// </param>
        /// <param name="component_types">
        ///    Optional argument
        ///    The type of each component in a tuple.
        /// </param>
        /// <param name="timeout_ms">
        ///    If the queue is empty, this operation will block for up to
        ///    timeout_ms milliseconds.
        ///    Note: This option is not supported yet.
        /// </param>
        /// <returns>
        ///    One or more tensors that were dequeued as a tuple.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation has k outputs, where k is the number of components
        ///    in the tuples stored in the given queue, and output i is the ith
        ///    component of the dequeued tuple.
        ///    
        ///    N.B. If the queue is empty, this operation will block until an element
        ///    has been dequeued (or 'timeout_ms' elapses, if specified).
        /// </remarks>
        public static Tensor[] queue_dequeue (Tensor handle, TF_DataType[] component_types, int? timeout_ms = null, string name = "QueueDequeue")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["component_types"] = component_types;
            if (timeout_ms.HasValue)
                dict["timeout_ms"] = timeout_ms.Value;
            var op = _op_def_lib._apply_op_helper("QueueDequeue", name: name, keywords: dict);
            int _idx = 0;
            var components = Enumerable.Range(0, op.OutputListLength("components")).Select(_ => op.outputs[_idx++]).ToArray();
            return (components);
        }

        /// <summary>
        ///    Dequeues <c>n</c> tuples of one or more tensors from the given queue.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a queue.
        /// </param>
        /// <param name="n">
        ///    The number of tuples to dequeue.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QueueDequeueMany'.
        /// </param>
        /// <param name="component_types">
        ///    Optional argument
        ///    The type of each component in a tuple.
        /// </param>
        /// <param name="timeout_ms">
        ///    If the queue has fewer than n elements, this operation
        ///    will block for up to timeout_ms milliseconds.
        ///    Note: This option is not supported yet.
        /// </param>
        /// <returns>
        ///    One or more tensors that were dequeued as a tuple.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    If the queue is closed and there are fewer than <c>n</c> elements, then an
        ///    OutOfRange error is returned.
        ///    
        ///    This operation concatenates queue-element component tensors along the
        ///    0th dimension to make a single component tensor.  All of the components
        ///    in the dequeued tuple will have size <c>n</c> in the 0th dimension.
        ///    
        ///    This operation has <c>k</c> outputs, where <c>k</c> is the number of components in
        ///    the tuples stored in the given queue, and output <c>i</c> is the ith
        ///    component of the dequeued tuple.
        ///    
        ///    N.B. If the queue is empty, this operation will block until <c>n</c> elements
        ///    have been dequeued (or 'timeout_ms' elapses, if specified).
        /// </remarks>
        public static Tensor[] queue_dequeue_many (Tensor handle, Tensor n, TF_DataType[] component_types, int? timeout_ms = null, string name = "QueueDequeueMany")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["n"] = n;
            dict["component_types"] = component_types;
            if (timeout_ms.HasValue)
                dict["timeout_ms"] = timeout_ms.Value;
            var op = _op_def_lib._apply_op_helper("QueueDequeueMany", name: name, keywords: dict);
            int _idx = 0;
            var components = Enumerable.Range(0, op.OutputListLength("components")).Select(_ => op.outputs[_idx++]).ToArray();
            return (components);
        }

        /// <summary>
        ///    Dequeues <c>n</c> tuples of one or more tensors from the given queue.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a queue.
        /// </param>
        /// <param name="n">
        ///    The number of tuples to dequeue.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QueueDequeueManyV2'.
        /// </param>
        /// <param name="component_types">
        ///    Optional argument
        ///    The type of each component in a tuple.
        /// </param>
        /// <param name="timeout_ms">
        ///    If the queue has fewer than n elements, this operation
        ///    will block for up to timeout_ms milliseconds.
        ///    Note: This option is not supported yet.
        /// </param>
        /// <returns>
        ///    One or more tensors that were dequeued as a tuple.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    If the queue is closed and there are fewer than <c>n</c> elements, then an
        ///    OutOfRange error is returned.
        ///    
        ///    This operation concatenates queue-element component tensors along the
        ///    0th dimension to make a single component tensor.  All of the components
        ///    in the dequeued tuple will have size <c>n</c> in the 0th dimension.
        ///    
        ///    This operation has <c>k</c> outputs, where <c>k</c> is the number of components in
        ///    the tuples stored in the given queue, and output <c>i</c> is the ith
        ///    component of the dequeued tuple.
        ///    
        ///    N.B. If the queue is empty, this operation will block until <c>n</c> elements
        ///    have been dequeued (or 'timeout_ms' elapses, if specified).
        /// </remarks>
        public static Tensor[] queue_dequeue_many_v2 (Tensor handle, Tensor n, TF_DataType[] component_types, int? timeout_ms = null, string name = "QueueDequeueManyV2")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["n"] = n;
            dict["component_types"] = component_types;
            if (timeout_ms.HasValue)
                dict["timeout_ms"] = timeout_ms.Value;
            var op = _op_def_lib._apply_op_helper("QueueDequeueManyV2", name: name, keywords: dict);
            int _idx = 0;
            var components = Enumerable.Range(0, op.OutputListLength("components")).Select(_ => op.outputs[_idx++]).ToArray();
            return (components);
        }

        /// <summary>
        ///    Dequeues <c>n</c> tuples of one or more tensors from the given queue.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a queue.
        /// </param>
        /// <param name="n">
        ///    The number of tuples to dequeue.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QueueDequeueUpTo'.
        /// </param>
        /// <param name="component_types">
        ///    Optional argument
        ///    The type of each component in a tuple.
        /// </param>
        /// <param name="timeout_ms">
        ///    If the queue has fewer than n elements, this operation
        ///    will block for up to timeout_ms milliseconds.
        ///    Note: This option is not supported yet.
        /// </param>
        /// <returns>
        ///    One or more tensors that were dequeued as a tuple.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation is not supported by all queues.  If a queue does not support
        ///    DequeueUpTo, then an Unimplemented error is returned.
        ///    
        ///    If the queue is closed and there are more than 0 but less than <c>n</c>
        ///    elements remaining, then instead of returning an OutOfRange error like
        ///    QueueDequeueMany, less than <c>n</c> elements are returned immediately.  If
        ///    the queue is closed and there are 0 elements left in the queue, then
        ///    an OutOfRange error is returned just like in QueueDequeueMany.
        ///    Otherwise the behavior is identical to QueueDequeueMany:
        ///    
        ///    This operation concatenates queue-element component tensors along the
        ///    0th dimension to make a single component tensor.  All of the components
        ///    in the dequeued tuple will have size <c>n</c> in the 0th dimension.
        ///    
        ///    This operation has k outputs, where <c>k</c> is the number of components in
        ///    the tuples stored in the given queue, and output <c>i</c> is the ith
        ///    component of the dequeued tuple.
        /// </remarks>
        public static Tensor[] queue_dequeue_up_to (Tensor handle, Tensor n, TF_DataType[] component_types, int? timeout_ms = null, string name = "QueueDequeueUpTo")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["n"] = n;
            dict["component_types"] = component_types;
            if (timeout_ms.HasValue)
                dict["timeout_ms"] = timeout_ms.Value;
            var op = _op_def_lib._apply_op_helper("QueueDequeueUpTo", name: name, keywords: dict);
            int _idx = 0;
            var components = Enumerable.Range(0, op.OutputListLength("components")).Select(_ => op.outputs[_idx++]).ToArray();
            return (components);
        }

        /// <summary>
        ///    Dequeues <c>n</c> tuples of one or more tensors from the given queue.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a queue.
        /// </param>
        /// <param name="n">
        ///    The number of tuples to dequeue.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QueueDequeueUpToV2'.
        /// </param>
        /// <param name="component_types">
        ///    Optional argument
        ///    The type of each component in a tuple.
        /// </param>
        /// <param name="timeout_ms">
        ///    If the queue has fewer than n elements, this operation
        ///    will block for up to timeout_ms milliseconds.
        ///    Note: This option is not supported yet.
        /// </param>
        /// <returns>
        ///    One or more tensors that were dequeued as a tuple.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation is not supported by all queues.  If a queue does not support
        ///    DequeueUpTo, then an Unimplemented error is returned.
        ///    
        ///    If the queue is closed and there are more than 0 but less than <c>n</c>
        ///    elements remaining, then instead of returning an OutOfRange error like
        ///    QueueDequeueMany, less than <c>n</c> elements are returned immediately.  If
        ///    the queue is closed and there are 0 elements left in the queue, then
        ///    an OutOfRange error is returned just like in QueueDequeueMany.
        ///    Otherwise the behavior is identical to QueueDequeueMany:
        ///    
        ///    This operation concatenates queue-element component tensors along the
        ///    0th dimension to make a single component tensor.  All of the components
        ///    in the dequeued tuple will have size n in the 0th dimension.
        ///    
        ///    This operation has <c>k</c> outputs, where <c>k</c> is the number of components in
        ///    the tuples stored in the given queue, and output <c>i</c> is the ith
        ///    component of the dequeued tuple.
        /// </remarks>
        public static Tensor[] queue_dequeue_up_to_v2 (Tensor handle, Tensor n, TF_DataType[] component_types, int? timeout_ms = null, string name = "QueueDequeueUpToV2")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["n"] = n;
            dict["component_types"] = component_types;
            if (timeout_ms.HasValue)
                dict["timeout_ms"] = timeout_ms.Value;
            var op = _op_def_lib._apply_op_helper("QueueDequeueUpToV2", name: name, keywords: dict);
            int _idx = 0;
            var components = Enumerable.Range(0, op.OutputListLength("components")).Select(_ => op.outputs[_idx++]).ToArray();
            return (components);
        }

        /// <summary>
        ///    Dequeues a tuple of one or more tensors from the given queue.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a queue.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QueueDequeueV2'.
        /// </param>
        /// <param name="component_types">
        ///    Optional argument
        ///    The type of each component in a tuple.
        /// </param>
        /// <param name="timeout_ms">
        ///    If the queue is empty, this operation will block for up to
        ///    timeout_ms milliseconds.
        ///    Note: This option is not supported yet.
        /// </param>
        /// <returns>
        ///    One or more tensors that were dequeued as a tuple.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation has k outputs, where k is the number of components
        ///    in the tuples stored in the given queue, and output i is the ith
        ///    component of the dequeued tuple.
        ///    
        ///    N.B. If the queue is empty, this operation will block until an element
        ///    has been dequeued (or 'timeout_ms' elapses, if specified).
        /// </remarks>
        public static Tensor[] queue_dequeue_v2 (Tensor handle, TF_DataType[] component_types, int? timeout_ms = null, string name = "QueueDequeueV2")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["component_types"] = component_types;
            if (timeout_ms.HasValue)
                dict["timeout_ms"] = timeout_ms.Value;
            var op = _op_def_lib._apply_op_helper("QueueDequeueV2", name: name, keywords: dict);
            int _idx = 0;
            var components = Enumerable.Range(0, op.OutputListLength("components")).Select(_ => op.outputs[_idx++]).ToArray();
            return (components);
        }

        /// <summary>
        ///    Enqueues a tuple of one or more tensors in the given queue.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a queue.
        /// </param>
        /// <param name="components">
        ///    One or more tensors from which the enqueued tensors should be taken.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QueueEnqueue'.
        /// </param>
        /// <param name="timeout_ms">
        ///    If the queue is full, this operation will block for up to
        ///    timeout_ms milliseconds.
        ///    Note: This option is not supported yet.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    The components input has k elements, which correspond to the components of
        ///    tuples stored in the given queue.
        ///    
        ///    N.B. If the queue is full, this operation will block until the given
        ///    element has been enqueued (or 'timeout_ms' elapses, if specified).
        /// </remarks>
        public static Operation queue_enqueue (Tensor handle, Tensor[] components, int? timeout_ms = null, string name = "QueueEnqueue")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["components"] = components;
            if (timeout_ms.HasValue)
                dict["timeout_ms"] = timeout_ms.Value;
            var op = _op_def_lib._apply_op_helper("QueueEnqueue", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Enqueues zero or more tuples of one or more tensors in the given queue.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a queue.
        /// </param>
        /// <param name="components">
        ///    One or more tensors from which the enqueued tensors should
        ///    be taken.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QueueEnqueueMany'.
        /// </param>
        /// <param name="timeout_ms">
        ///    If the queue is too full, this operation will block for up
        ///    to timeout_ms milliseconds.
        ///    Note: This option is not supported yet.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    This operation slices each component tensor along the 0th dimension to
        ///    make multiple queue elements. All of the tuple components must have the
        ///    same size in the 0th dimension.
        ///    
        ///    The components input has k elements, which correspond to the components of
        ///    tuples stored in the given queue.
        ///    
        ///    N.B. If the queue is full, this operation will block until the given
        ///    elements have been enqueued (or 'timeout_ms' elapses, if specified).
        /// </remarks>
        public static Operation queue_enqueue_many (Tensor handle, Tensor[] components, int? timeout_ms = null, string name = "QueueEnqueueMany")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["components"] = components;
            if (timeout_ms.HasValue)
                dict["timeout_ms"] = timeout_ms.Value;
            var op = _op_def_lib._apply_op_helper("QueueEnqueueMany", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Enqueues zero or more tuples of one or more tensors in the given queue.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a queue.
        /// </param>
        /// <param name="components">
        ///    One or more tensors from which the enqueued tensors should
        ///    be taken.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QueueEnqueueManyV2'.
        /// </param>
        /// <param name="timeout_ms">
        ///    If the queue is too full, this operation will block for up
        ///    to timeout_ms milliseconds.
        ///    Note: This option is not supported yet.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    This operation slices each component tensor along the 0th dimension to
        ///    make multiple queue elements. All of the tuple components must have the
        ///    same size in the 0th dimension.
        ///    
        ///    The components input has k elements, which correspond to the components of
        ///    tuples stored in the given queue.
        ///    
        ///    N.B. If the queue is full, this operation will block until the given
        ///    elements have been enqueued (or 'timeout_ms' elapses, if specified).
        /// </remarks>
        public static Operation queue_enqueue_many_v2 (Tensor handle, Tensor[] components, int? timeout_ms = null, string name = "QueueEnqueueManyV2")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["components"] = components;
            if (timeout_ms.HasValue)
                dict["timeout_ms"] = timeout_ms.Value;
            var op = _op_def_lib._apply_op_helper("QueueEnqueueManyV2", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Enqueues a tuple of one or more tensors in the given queue.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a queue.
        /// </param>
        /// <param name="components">
        ///    One or more tensors from which the enqueued tensors should be taken.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QueueEnqueueV2'.
        /// </param>
        /// <param name="timeout_ms">
        ///    If the queue is full, this operation will block for up to
        ///    timeout_ms milliseconds.
        ///    Note: This option is not supported yet.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    The components input has k elements, which correspond to the components of
        ///    tuples stored in the given queue.
        ///    
        ///    N.B. If the queue is full, this operation will block until the given
        ///    element has been enqueued (or 'timeout_ms' elapses, if specified).
        /// </remarks>
        public static Operation queue_enqueue_v2 (Tensor handle, Tensor[] components, int? timeout_ms = null, string name = "QueueEnqueueV2")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["components"] = components;
            if (timeout_ms.HasValue)
                dict["timeout_ms"] = timeout_ms.Value;
            var op = _op_def_lib._apply_op_helper("QueueEnqueueV2", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Returns true if queue is closed.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a queue.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QueueIsClosed'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation returns true if the queue is closed and false if the queue
        ///    is open.
        /// </remarks>
        public static Tensor queue_is_closed (Tensor handle, string name = "QueueIsClosed")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            var op = _op_def_lib._apply_op_helper("QueueIsClosed", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns true if queue is closed.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a queue.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QueueIsClosedV2'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation returns true if the queue is closed and false if the queue
        ///    is open.
        /// </remarks>
        public static Tensor queue_is_closed_v2 (Tensor handle, string name = "QueueIsClosedV2")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            var op = _op_def_lib._apply_op_helper("QueueIsClosedV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the number of elements in the given queue.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a queue.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QueueSize'.
        /// </param>
        /// <returns>
        ///    The number of elements in the given queue.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor queue_size (Tensor handle, string name = "QueueSize")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            var op = _op_def_lib._apply_op_helper("QueueSize", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the number of elements in the given queue.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a queue.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'QueueSizeV2'.
        /// </param>
        /// <returns>
        ///    The number of elements in the given queue.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor queue_size_v2 (Tensor handle, string name = "QueueSizeV2")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            var op = _op_def_lib._apply_op_helper("QueueSizeV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Real-valued fast Fourier transform.
        /// </summary>
        /// <param name="input">
        ///    A float32 tensor.
        /// </param>
        /// <param name="fft_length">
        ///    An int32 tensor of shape [1]. The FFT length.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RFFT'.
        /// </param>
        /// <returns>
        ///    A complex64 tensor of the same rank as <c>input</c>. The inner-most
        ///    dimension of <c>input</c> is replaced with the <c>fft_length / 2 + 1</c> unique
        ///    frequency components of its 1D Fourier transform.
        ///    
        ///    @compatibility(numpy)
        ///    Equivalent to np.fft.rfft
        ///    @end_compatibility
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Computes the 1-dimensional discrete Fourier transform of a real-valued signal
        ///    over the inner-most dimension of <c>input</c>.
        ///    
        ///    Since the DFT of a real signal is Hermitian-symmetric, <c>RFFT</c> only returns the
        ///    <c>fft_length / 2 + 1</c> unique components of the FFT: the zero-frequency term,
        ///    followed by the <c>fft_length / 2</c> positive-frequency terms.
        ///    
        ///    Along the axis <c>RFFT</c> is computed on, if <c>fft_length</c> is smaller than the
        ///    corresponding dimension of <c>input</c>, the dimension is cropped. If it is larger,
        ///    the dimension is padded with zeros.
        /// </remarks>
        public static Tensor r_f_f_t (Tensor input, Tensor fft_length, string name = "RFFT")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["fft_length"] = fft_length;
            var op = _op_def_lib._apply_op_helper("RFFT", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    2D real-valued fast Fourier transform.
        /// </summary>
        /// <param name="input">
        ///    A float32 tensor.
        /// </param>
        /// <param name="fft_length">
        ///    An int32 tensor of shape [2]. The FFT length for each dimension.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RFFT2D'.
        /// </param>
        /// <returns>
        ///    A complex64 tensor of the same rank as <c>input</c>. The inner-most 2
        ///    dimensions of <c>input</c> are replaced with their 2D Fourier transform. The
        ///    inner-most dimension contains <c>fft_length / 2 + 1</c> unique frequency
        ///    components.
        ///    
        ///    @compatibility(numpy)
        ///    Equivalent to np.fft.rfft2
        ///    @end_compatibility
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Computes the 2-dimensional discrete Fourier transform of a real-valued signal
        ///    over the inner-most 2 dimensions of <c>input</c>.
        ///    
        ///    Since the DFT of a real signal is Hermitian-symmetric, <c>RFFT2D</c> only returns the
        ///    <c>fft_length / 2 + 1</c> unique components of the FFT for the inner-most dimension
        ///    of <c>output</c>: the zero-frequency term, followed by the <c>fft_length / 2</c>
        ///    positive-frequency terms.
        ///    
        ///    Along each axis <c>RFFT2D</c> is computed on, if <c>fft_length</c> is smaller than the
        ///    corresponding dimension of <c>input</c>, the dimension is cropped. If it is larger,
        ///    the dimension is padded with zeros.
        /// </remarks>
        public static Tensor r_f_f_t2d (Tensor input, Tensor fft_length, string name = "RFFT2D")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["fft_length"] = fft_length;
            var op = _op_def_lib._apply_op_helper("RFFT2D", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    3D real-valued fast Fourier transform.
        /// </summary>
        /// <param name="input">
        ///    A float32 tensor.
        /// </param>
        /// <param name="fft_length">
        ///    An int32 tensor of shape [3]. The FFT length for each dimension.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RFFT3D'.
        /// </param>
        /// <returns>
        ///    A complex64 tensor of the same rank as <c>input</c>. The inner-most 3
        ///    dimensions of <c>input</c> are replaced with the their 3D Fourier transform. The
        ///    inner-most dimension contains <c>fft_length / 2 + 1</c> unique frequency
        ///    components.
        ///    
        ///    @compatibility(numpy)
        ///    Equivalent to np.fft.rfftn with 3 dimensions.
        ///    @end_compatibility
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Computes the 3-dimensional discrete Fourier transform of a real-valued signal
        ///    over the inner-most 3 dimensions of <c>input</c>.
        ///    
        ///    Since the DFT of a real signal is Hermitian-symmetric, <c>RFFT3D</c> only returns the
        ///    <c>fft_length / 2 + 1</c> unique components of the FFT for the inner-most dimension
        ///    of <c>output</c>: the zero-frequency term, followed by the <c>fft_length / 2</c>
        ///    positive-frequency terms.
        ///    
        ///    Along each axis <c>RFFT3D</c> is computed on, if <c>fft_length</c> is smaller than the
        ///    corresponding dimension of <c>input</c>, the dimension is cropped. If it is larger,
        ///    the dimension is padded with zeros.
        /// </remarks>
        public static Tensor r_f_f_t3d (Tensor input, Tensor fft_length, string name = "RFFT3D")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["fft_length"] = fft_length;
            var op = _op_def_lib._apply_op_helper("RFFT3D", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Converts one or more images from RGB to HSV.
        /// </summary>
        /// <param name="images">
        ///    1-D or higher rank. RGB data to convert. Last dimension must be size 3.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RGBToHSV'.
        /// </param>
        /// <returns>
        ///    <c>images</c> converted to HSV.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Outputs a tensor of the same shape as the <c>images</c> tensor, containing the HSV
        ///    value of the pixels. The output is only well defined if the value in <c>images</c>
        ///    are in <c>[0,1]</c>.
        ///    
        ///    <c>output[..., 0]</c> contains hue, <c>output[..., 1]</c> contains saturation, and
        ///    <c>output[..., 2]</c> contains value. All HSV values are in <c>[0,1]</c>. A hue of 0
        ///    corresponds to pure red, hue 1/3 is pure green, and 2/3 is pure blue.
        /// </remarks>
        public static Tensor r_g_b_to_h_s_v (Tensor images, string name = "RGBToHSV")
        {
            var dict = new Dictionary<string, object>();
            dict["images"] = images;
            var op = _op_def_lib._apply_op_helper("RGBToHSV", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Randomly crop <c>image</c>.
        /// </summary>
        /// <param name="image">
        ///    3-D of shape <c>[height, width, channels]</c>.
        /// </param>
        /// <param name="size">
        ///    1-D of length 2 containing: <c>crop_height</c>, <c>crop_width</c>..
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RandomCrop'.
        /// </param>
        /// <param name="seed">
        ///    If either seed or seed2 are set to be non-zero, the random number
        ///    generator is seeded by the given seed.  Otherwise, it is seeded by a
        ///    random seed.
        /// </param>
        /// <param name="seed2">
        ///    An second seed to avoid seed collision.
        /// </param>
        /// <returns>
        ///    3-D of shape <c>[crop_height, crop_width, channels].</c>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    <c>size</c> is a 1-D int64 tensor with 2 elements representing the crop height and
        ///    width.  The values must be non negative.
        ///    
        ///    This Op picks a random location in <c>image</c> and crops a <c>height</c> by <c>width</c>
        ///    rectangle from that location.  The random location is picked so the cropped
        ///    area will fit inside the original image.
        /// </remarks>
        public static Tensor random_crop (Tensor image, Tensor size, int? seed = null, int? seed2 = null, string name = "RandomCrop")
        {
            var dict = new Dictionary<string, object>();
            dict["image"] = image;
            dict["size"] = size;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("RandomCrop", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a Dataset that returns pseudorandom numbers.
        /// </summary>
        /// <param name="seed">
        ///    A scalar seed for the random number generator. If either seed or
        ///    seed2 is set to be non-zero, the random number generator is seeded
        ///    by the given seed.  Otherwise, a random seed is used.
        /// </param>
        /// <param name="seed2">
        ///    A second scalar seed to avoid seed collision.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RandomDataset'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor random_dataset (Tensor seed, Tensor seed2, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "RandomDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["seed"] = seed;
            dict["seed2"] = seed2;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("RandomDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Outputs random values from the Gamma distribution(s) described by alpha.
        /// </summary>
        /// <param name="shape">
        ///    1-D integer tensor. Shape of independent samples to draw from each
        ///    distribution described by the shape parameters given in alpha.
        /// </param>
        /// <param name="alpha">
        ///    A tensor in which each scalar is a "shape" parameter describing the
        ///    associated gamma distribution.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RandomGamma'.
        /// </param>
        /// <param name="seed">
        ///    If either <c>seed</c> or <c>seed2</c> are set to be non-zero, the random number
        ///    generator is seeded by the given seed.  Otherwise, it is seeded by a
        ///    random seed.
        /// </param>
        /// <param name="seed2">
        ///    A second seed to avoid seed collision.
        /// </param>
        /// <returns>
        ///    A tensor with shape <c>shape + shape(alpha)</c>. Each slice
        ///    <c>[:, ..., :, i0, i1, ...iN]</c> contains the samples drawn for
        ///    <c>alpha[i0, i1, ...iN]</c>. The dtype of the output matches the dtype of alpha.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op uses the algorithm by Marsaglia et al. to acquire samples via
        ///    transformation-rejection from pairs of uniform and normal random variables.
        ///    See http://dl.acm.org/citation.cfm?id=358414
        /// </remarks>
        public static Tensor random_gamma (Tensor shape, Tensor alpha, int? seed = null, int? seed2 = null, string name = "RandomGamma")
        {
            var dict = new Dictionary<string, object>();
            dict["shape"] = shape;
            dict["alpha"] = alpha;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("RandomGamma", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the derivative of a Gamma random sample w.r.t. <c>alpha</c>.
        /// </summary>
        /// <param name="alpha">
        /// </param>
        /// <param name="sample">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RandomGammaGrad'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor random_gamma_grad (Tensor alpha, Tensor sample, string name = "RandomGammaGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["alpha"] = alpha;
            dict["sample"] = sample;
            var op = _op_def_lib._apply_op_helper("RandomGammaGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Use RandomPoissonV2 instead.
        /// </summary>
        /// <param name="shape">
        /// </param>
        /// <param name="rate">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RandomPoisson'.
        /// </param>
        /// <param name="seed">
        /// </param>
        /// <param name="seed2">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor random_poisson (Tensor shape, Tensor rate, int? seed = null, int? seed2 = null, string name = "RandomPoisson")
        {
            var dict = new Dictionary<string, object>();
            dict["shape"] = shape;
            dict["rate"] = rate;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("RandomPoisson", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Outputs random values from the Poisson distribution(s) described by rate.
        /// </summary>
        /// <param name="shape">
        ///    1-D integer tensor. Shape of independent samples to draw from each
        ///    distribution described by the shape parameters given in rate.
        /// </param>
        /// <param name="rate">
        ///    A tensor in which each scalar is a "rate" parameter describing the
        ///    associated poisson distribution.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RandomPoissonV2'.
        /// </param>
        /// <param name="seed">
        ///    If either <c>seed</c> or <c>seed2</c> are set to be non-zero, the random number
        ///    generator is seeded by the given seed.  Otherwise, it is seeded by a
        ///    random seed.
        /// </param>
        /// <param name="seed2">
        ///    A second seed to avoid seed collision.
        /// </param>
        /// <param name="dtype">
        /// </param>
        /// <returns>
        ///    A tensor with shape <c>shape + shape(rate)</c>. Each slice
        ///    <c>[:, ..., :, i0, i1, ...iN]</c> contains the samples drawn for
        ///    <c>rate[i0, i1, ...iN]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op uses two algorithms, depending on rate. If rate &amp;gt;= 10, then
        ///    the algorithm by Hormann is used to acquire samples via
        ///    transformation-rejection.
        ///    See http://www.sciencedirect.com/science/article/pii/0167668793909974.
        ///    
        ///    Otherwise, Knuth's algorithm is used to acquire samples via multiplying uniform
        ///    random variables.
        ///    See Donald E. Knuth (1969). Seminumerical Algorithms. The Art of Computer
        ///    Programming, Volume 2. Addison Wesley
        /// </remarks>
        public static Tensor random_poisson_v2 (Tensor shape, Tensor rate, int? seed = null, int? seed2 = null, TF_DataType? dtype = null, string name = "RandomPoissonV2")
        {
            var dict = new Dictionary<string, object>();
            dict["shape"] = shape;
            dict["rate"] = rate;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            if (dtype.HasValue)
                dict["dtype"] = dtype.Value;
            var op = _op_def_lib._apply_op_helper("RandomPoissonV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Randomly shuffles a tensor along its first dimension.
        /// </summary>
        /// <param name="value">
        ///    The tensor to be shuffled.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RandomShuffle'.
        /// </param>
        /// <param name="seed">
        ///    If either <c>seed</c> or <c>seed2</c> are set to be non-zero, the random number
        ///    generator is seeded by the given seed.  Otherwise, it is seeded by a
        ///    random seed.
        /// </param>
        /// <param name="seed2">
        ///    A second seed to avoid seed collision.
        /// </param>
        /// <returns>
        ///    A tensor of same shape and type as <c>value</c>, shuffled along its first
        ///    dimension.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The tensor is shuffled along dimension 0, such that each <c>value[j]</c> is mapped
        ///    to one and only one <c>output[i]</c>. For example, a mapping that might occur for a
        ///    3x2 tensor is:
        ///    
        ///   <code>
        ///    [[1, 2],       [[5, 6],
        ///    [3, 4],  ==&amp;gt;   [1, 2],
        ///    [5, 6]]        [3, 4]]
        ///   </code>
        /// </remarks>
        public static Tensor random_shuffle (Tensor value, int? seed = null, int? seed2 = null, string name = "RandomShuffle")
        {
            var dict = new Dictionary<string, object>();
            dict["value"] = value;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("RandomShuffle", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A queue that randomizes the order of elements.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RandomShuffleQueue'.
        /// </param>
        /// <param name="component_types">
        ///    Optional argument
        ///    The type of each component in a value.
        /// </param>
        /// <param name="shapes">
        ///    The shape of each component in a value. The length of this attr must
        ///    be either 0 or the same as the length of component_types. If the length of
        ///    this attr is 0, the shapes of queue elements are not constrained, and
        ///    only one element may be dequeued at a time.
        /// </param>
        /// <param name="capacity">
        ///    The upper bound on the number of elements in this queue.
        ///    Negative numbers mean no limit.
        /// </param>
        /// <param name="min_after_dequeue">
        ///    Dequeue will block unless there would be this
        ///    many elements after the dequeue or the queue is closed. This
        ///    ensures a minimum level of mixing of elements.
        /// </param>
        /// <param name="seed">
        ///    If either seed or seed2 is set to be non-zero, the random number
        ///    generator is seeded by the given seed.  Otherwise, a random seed is used.
        /// </param>
        /// <param name="seed2">
        ///    A second seed to avoid seed collision.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this queue is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this queue will be shared under the given name
        ///    across multiple sessions.
        /// </param>
        /// <returns>
        ///    The handle to the queue.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor random_shuffle_queue (TF_DataType[] component_types, TensorShape[] shapes = null, int? capacity = null, int? min_after_dequeue = null, int? seed = null, int? seed2 = null, string container = null, string shared_name = null, string name = "RandomShuffleQueue")
        {
            var dict = new Dictionary<string, object>();
            dict["component_types"] = component_types;
            if (shapes != null)
                dict["shapes"] = shapes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (min_after_dequeue.HasValue)
                dict["min_after_dequeue"] = min_after_dequeue.Value;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("RandomShuffleQueue", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A queue that randomizes the order of elements.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RandomShuffleQueueV2'.
        /// </param>
        /// <param name="component_types">
        ///    Optional argument
        ///    The type of each component in a value.
        /// </param>
        /// <param name="shapes">
        ///    The shape of each component in a value. The length of this attr must
        ///    be either 0 or the same as the length of component_types. If the length of
        ///    this attr is 0, the shapes of queue elements are not constrained, and
        ///    only one element may be dequeued at a time.
        /// </param>
        /// <param name="capacity">
        ///    The upper bound on the number of elements in this queue.
        ///    Negative numbers mean no limit.
        /// </param>
        /// <param name="min_after_dequeue">
        ///    Dequeue will block unless there would be this
        ///    many elements after the dequeue or the queue is closed. This
        ///    ensures a minimum level of mixing of elements.
        /// </param>
        /// <param name="seed">
        ///    If either seed or seed2 is set to be non-zero, the random number
        ///    generator is seeded by the given seed.  Otherwise, a random seed is used.
        /// </param>
        /// <param name="seed2">
        ///    A second seed to avoid seed collision.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this queue is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this queue will be shared under the given name
        ///    across multiple sessions.
        /// </param>
        /// <returns>
        ///    The handle to the queue.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor random_shuffle_queue_v2 (TF_DataType[] component_types, TensorShape[] shapes = null, int? capacity = null, int? min_after_dequeue = null, int? seed = null, int? seed2 = null, string container = null, string shared_name = null, string name = "RandomShuffleQueueV2")
        {
            var dict = new Dictionary<string, object>();
            dict["component_types"] = component_types;
            if (shapes != null)
                dict["shapes"] = shapes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (min_after_dequeue.HasValue)
                dict["min_after_dequeue"] = min_after_dequeue.Value;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("RandomShuffleQueueV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Outputs random values from a normal distribution.
        /// </summary>
        /// <param name="shape">
        ///    The shape of the output tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RandomStandardNormal'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The type of the output.
        /// </param>
        /// <param name="seed">
        ///    If either <c>seed</c> or <c>seed2</c> are set to be non-zero, the random number
        ///    generator is seeded by the given seed.  Otherwise, it is seeded by a
        ///    random seed.
        /// </param>
        /// <param name="seed2">
        ///    A second seed to avoid seed collision.
        /// </param>
        /// <returns>
        ///    A tensor of the specified shape filled with random normal values.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The generated values will have mean 0 and standard deviation 1.
        /// </remarks>
        public static Tensor random_standard_normal (Tensor shape, TF_DataType dtype, int? seed = null, int? seed2 = null, string name = "RandomStandardNormal")
        {
            var dict = new Dictionary<string, object>();
            dict["shape"] = shape;
            dict["dtype"] = dtype;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("RandomStandardNormal", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Outputs random values from a uniform distribution.
        /// </summary>
        /// <param name="shape">
        ///    The shape of the output tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RandomUniform'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The type of the output.
        /// </param>
        /// <param name="seed">
        ///    If either <c>seed</c> or <c>seed2</c> are set to be non-zero, the random number
        ///    generator is seeded by the given seed.  Otherwise, it is seeded by a
        ///    random seed.
        /// </param>
        /// <param name="seed2">
        ///    A second seed to avoid seed collision.
        /// </param>
        /// <returns>
        ///    A tensor of the specified shape filled with uniform random values.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The generated values follow a uniform distribution in the range <c>[0, 1)</c>. The
        ///    lower bound 0 is included in the range, while the upper bound 1 is excluded.
        /// </remarks>
        public static Tensor random_uniform (Tensor shape, TF_DataType dtype, int? seed = null, int? seed2 = null, string name = "RandomUniform")
        {
            var dict = new Dictionary<string, object>();
            dict["shape"] = shape;
            dict["dtype"] = dtype;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("RandomUniform", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Outputs random integers from a uniform distribution.
        /// </summary>
        /// <param name="shape">
        ///    The shape of the output tensor.
        /// </param>
        /// <param name="minval">
        ///    0-D.  Inclusive lower bound on the generated integers.
        /// </param>
        /// <param name="maxval">
        ///    0-D.  Exclusive upper bound on the generated integers.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RandomUniformInt'.
        /// </param>
        /// <param name="seed">
        ///    If either <c>seed</c> or <c>seed2</c> are set to be non-zero, the random number
        ///    generator is seeded by the given seed.  Otherwise, it is seeded by a
        ///    random seed.
        /// </param>
        /// <param name="seed2">
        ///    A second seed to avoid seed collision.
        /// </param>
        /// <returns>
        ///    A tensor of the specified shape filled with uniform random integers.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The generated values are uniform integers in the range <c>[minval, maxval)</c>.
        ///    The lower bound <c>minval</c> is included in the range, while the upper bound
        ///    <c>maxval</c> is excluded.
        ///    
        ///    The random integers are slightly biased unless <c>maxval - minval</c> is an exact
        ///    power of two.  The bias is small for values of <c>maxval - minval</c> significantly
        ///    smaller than the range of the output (either <c>2^32</c> or <c>2^64</c>).
        /// </remarks>
        public static Tensor random_uniform_int (Tensor shape, Tensor minval, Tensor maxval, int? seed = null, int? seed2 = null, string name = "RandomUniformInt")
        {
            var dict = new Dictionary<string, object>();
            dict["shape"] = shape;
            dict["minval"] = minval;
            dict["maxval"] = maxval;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("RandomUniformInt", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a sequence of numbers.
        /// </summary>
        /// <param name="start">
        ///    0-D (scalar). First entry in the sequence.
        /// </param>
        /// <param name="limit">
        ///    0-D (scalar). Upper limit of sequence, exclusive.
        /// </param>
        /// <param name="delta">
        ///    0-D (scalar). Optional. Default is 1. Number that increments <c>start</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Range'.
        /// </param>
        /// <returns>
        ///    1-D.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation creates a sequence of numbers that begins at <c>start</c> and
        ///    extends by increments of <c>delta</c> up to but not including <c>limit</c>.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # 'start' is 3
        ///    # 'limit' is 18
        ///    # 'delta' is 3
        ///    tf.range(start, limit, delta) ==&amp;gt; [3, 6, 9, 12, 15]
        ///   </code>
        /// </remarks>
        public static Tensor range (Tensor start, Tensor limit, Tensor delta, string name = "Range")
        {
            var dict = new Dictionary<string, object>();
            dict["start"] = start;
            dict["limit"] = limit;
            dict["delta"] = delta;
            var op = _op_def_lib._apply_op_helper("Range", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a dataset with a range of values. Corresponds to python's xrange.
        /// </summary>
        /// <param name="start">
        ///    corresponds to start in python's xrange().
        /// </param>
        /// <param name="stop">
        ///    corresponds to stop in python's xrange().
        /// </param>
        /// <param name="step">
        ///    corresponds to step in python's xrange().
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RangeDataset'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor range_dataset (Tensor start, Tensor stop, Tensor step, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "RangeDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["start"] = start;
            dict["stop"] = stop;
            dict["step"] = step;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("RangeDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the rank of a tensor.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Rank'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation returns an integer representing the rank of <c>input</c>.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # 't' is [[[1, 1, 1], [2, 2, 2]], [[3, 3, 3], [4, 4, 4]]]
        ///    # shape of tensor 't' is [2, 2, 3]
        ///    rank(t) ==&amp;gt; 3
        ///   </code>
        ///    
        ///    **Note**: The rank of a tensor is not the same as the rank of a matrix. The rank
        ///    of a tensor is the number of indices required to uniquely select each element
        ///    of the tensor. Rank is also known as "order", "degree", or "ndims."
        /// </remarks>
        public static Tensor rank (Tensor input, string name = "Rank")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("Rank", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Reads and outputs the entire contents of the input filename.
        /// </summary>
        /// <param name="filename">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReadFile'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor read_file (Tensor filename, string name = "ReadFile")
        {
            var dict = new Dictionary<string, object>();
            dict["filename"] = filename;
            var op = _op_def_lib._apply_op_helper("ReadFile", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Reads the value of a variable.
        /// </summary>
        /// <param name="resource">
        ///    handle to the resource in which to store the variable.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReadVariableOp'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    the dtype of the value.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The tensor returned by this operation is immutable.
        ///    
        ///    The value returned by this operation is guaranteed to be influenced by all the
        ///    writes on which this operation depends directly or indirectly, and to not be
        ///    influenced by any of the writes which depend directly or indirectly on this
        ///    operation.
        /// </remarks>
        public static Tensor read_variable_op (Tensor resource, TF_DataType dtype, string name = "ReadVariableOp")
        {
            var dict = new Dictionary<string, object>();
            dict["resource"] = resource;
            dict["dtype"] = dtype;
            var op = _op_def_lib._apply_op_helper("ReadVariableOp", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the number of records this Reader has produced.
        /// </summary>
        /// <param name="reader_handle">
        ///    Handle to a Reader.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReaderNumRecordsProduced'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This is the same as the number of ReaderRead executions that have
        ///    succeeded.
        /// </remarks>
        public static Tensor reader_num_records_produced (Tensor reader_handle, string name = "ReaderNumRecordsProduced")
        {
            var dict = new Dictionary<string, object>();
            dict["reader_handle"] = reader_handle;
            var op = _op_def_lib._apply_op_helper("ReaderNumRecordsProduced", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the number of records this Reader has produced.
        /// </summary>
        /// <param name="reader_handle">
        ///    Handle to a Reader.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReaderNumRecordsProducedV2'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This is the same as the number of ReaderRead executions that have
        ///    succeeded.
        /// </remarks>
        public static Tensor reader_num_records_produced_v2 (Tensor reader_handle, string name = "ReaderNumRecordsProducedV2")
        {
            var dict = new Dictionary<string, object>();
            dict["reader_handle"] = reader_handle;
            var op = _op_def_lib._apply_op_helper("ReaderNumRecordsProducedV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the number of work units this Reader has finished processing.
        /// </summary>
        /// <param name="reader_handle">
        ///    Handle to a Reader.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReaderNumWorkUnitsCompleted'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor reader_num_work_units_completed (Tensor reader_handle, string name = "ReaderNumWorkUnitsCompleted")
        {
            var dict = new Dictionary<string, object>();
            dict["reader_handle"] = reader_handle;
            var op = _op_def_lib._apply_op_helper("ReaderNumWorkUnitsCompleted", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the number of work units this Reader has finished processing.
        /// </summary>
        /// <param name="reader_handle">
        ///    Handle to a Reader.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReaderNumWorkUnitsCompletedV2'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor reader_num_work_units_completed_v2 (Tensor reader_handle, string name = "ReaderNumWorkUnitsCompletedV2")
        {
            var dict = new Dictionary<string, object>();
            dict["reader_handle"] = reader_handle;
            var op = _op_def_lib._apply_op_helper("ReaderNumWorkUnitsCompletedV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the next record (key, value pair) produced by a Reader.
        /// </summary>
        /// <param name="reader_handle">
        ///    Handle to a Reader.
        /// </param>
        /// <param name="queue_handle">
        ///    Handle to a Queue, with string work items.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReaderRead'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    key : A scalar.
        ///    value : A scalar.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Will dequeue from the input queue if necessary (e.g. when the
        ///    Reader needs to start reading from a new file since it has finished
        ///    with the previous file).
        /// </remarks>
        public static (Tensor key, Tensor value) reader_read (Tensor reader_handle, Tensor queue_handle, string name = "ReaderRead")
        {
            var dict = new Dictionary<string, object>();
            dict["reader_handle"] = reader_handle;
            dict["queue_handle"] = queue_handle;
            var op = _op_def_lib._apply_op_helper("ReaderRead", name: name, keywords: dict);
            int _idx = 0;
            var key = op.outputs[_idx++];
            var value = op.outputs[_idx++];
            return (key, value);
        }

        /// <summary>
        ///    Returns up to <c>num_records</c> (key, value) pairs produced by a Reader.
        /// </summary>
        /// <param name="reader_handle">
        ///    Handle to a <c>Reader</c>.
        /// </param>
        /// <param name="queue_handle">
        ///    Handle to a <c>Queue</c>, with string work items.
        /// </param>
        /// <param name="num_records">
        ///    number of records to read from <c>Reader</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReaderReadUpTo'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    keys : A 1-D tensor.
        ///    values : A 1-D tensor.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Will dequeue from the input queue if necessary (e.g. when the
        ///    Reader needs to start reading from a new file since it has finished
        ///    with the previous file).
        ///    It may return less than <c>num_records</c> even before the last batch.
        /// </remarks>
        public static (Tensor keys, Tensor values) reader_read_up_to (Tensor reader_handle, Tensor queue_handle, Tensor num_records, string name = "ReaderReadUpTo")
        {
            var dict = new Dictionary<string, object>();
            dict["reader_handle"] = reader_handle;
            dict["queue_handle"] = queue_handle;
            dict["num_records"] = num_records;
            var op = _op_def_lib._apply_op_helper("ReaderReadUpTo", name: name, keywords: dict);
            int _idx = 0;
            var keys = op.outputs[_idx++];
            var values = op.outputs[_idx++];
            return (keys, values);
        }

        /// <summary>
        ///    Returns up to <c>num_records</c> (key, value) pairs produced by a Reader.
        /// </summary>
        /// <param name="reader_handle">
        ///    Handle to a <c>Reader</c>.
        /// </param>
        /// <param name="queue_handle">
        ///    Handle to a <c>Queue</c>, with string work items.
        /// </param>
        /// <param name="num_records">
        ///    number of records to read from <c>Reader</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReaderReadUpToV2'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    keys : A 1-D tensor.
        ///    values : A 1-D tensor.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Will dequeue from the input queue if necessary (e.g. when the
        ///    Reader needs to start reading from a new file since it has finished
        ///    with the previous file).
        ///    It may return less than <c>num_records</c> even before the last batch.
        /// </remarks>
        public static (Tensor keys, Tensor values) reader_read_up_to_v2 (Tensor reader_handle, Tensor queue_handle, Tensor num_records, string name = "ReaderReadUpToV2")
        {
            var dict = new Dictionary<string, object>();
            dict["reader_handle"] = reader_handle;
            dict["queue_handle"] = queue_handle;
            dict["num_records"] = num_records;
            var op = _op_def_lib._apply_op_helper("ReaderReadUpToV2", name: name, keywords: dict);
            int _idx = 0;
            var keys = op.outputs[_idx++];
            var values = op.outputs[_idx++];
            return (keys, values);
        }

        /// <summary>
        ///    Returns the next record (key, value pair) produced by a Reader.
        /// </summary>
        /// <param name="reader_handle">
        ///    Handle to a Reader.
        /// </param>
        /// <param name="queue_handle">
        ///    Handle to a Queue, with string work items.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReaderReadV2'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    key : A scalar.
        ///    value : A scalar.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Will dequeue from the input queue if necessary (e.g. when the
        ///    Reader needs to start reading from a new file since it has finished
        ///    with the previous file).
        /// </remarks>
        public static (Tensor key, Tensor value) reader_read_v2 (Tensor reader_handle, Tensor queue_handle, string name = "ReaderReadV2")
        {
            var dict = new Dictionary<string, object>();
            dict["reader_handle"] = reader_handle;
            dict["queue_handle"] = queue_handle;
            var op = _op_def_lib._apply_op_helper("ReaderReadV2", name: name, keywords: dict);
            int _idx = 0;
            var key = op.outputs[_idx++];
            var value = op.outputs[_idx++];
            return (key, value);
        }

        /// <summary>
        ///    Restore a Reader to its initial clean state.
        /// </summary>
        /// <param name="reader_handle">
        ///    Handle to a Reader.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReaderReset'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation reader_reset (Tensor reader_handle, string name = "ReaderReset")
        {
            var dict = new Dictionary<string, object>();
            dict["reader_handle"] = reader_handle;
            var op = _op_def_lib._apply_op_helper("ReaderReset", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Restore a Reader to its initial clean state.
        /// </summary>
        /// <param name="reader_handle">
        ///    Handle to a Reader.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReaderResetV2'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation reader_reset_v2 (Tensor reader_handle, string name = "ReaderResetV2")
        {
            var dict = new Dictionary<string, object>();
            dict["reader_handle"] = reader_handle;
            var op = _op_def_lib._apply_op_helper("ReaderResetV2", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Restore a reader to a previously saved state.
        /// </summary>
        /// <param name="reader_handle">
        ///    Handle to a Reader.
        /// </param>
        /// <param name="state">
        ///    Result of a ReaderSerializeState of a Reader with type
        ///    matching reader_handle.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReaderRestoreState'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    Not all Readers support being restored, so this can produce an
        ///    Unimplemented error.
        /// </remarks>
        public static Operation reader_restore_state (Tensor reader_handle, Tensor state, string name = "ReaderRestoreState")
        {
            var dict = new Dictionary<string, object>();
            dict["reader_handle"] = reader_handle;
            dict["state"] = state;
            var op = _op_def_lib._apply_op_helper("ReaderRestoreState", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Restore a reader to a previously saved state.
        /// </summary>
        /// <param name="reader_handle">
        ///    Handle to a Reader.
        /// </param>
        /// <param name="state">
        ///    Result of a ReaderSerializeState of a Reader with type
        ///    matching reader_handle.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReaderRestoreStateV2'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    Not all Readers support being restored, so this can produce an
        ///    Unimplemented error.
        /// </remarks>
        public static Operation reader_restore_state_v2 (Tensor reader_handle, Tensor state, string name = "ReaderRestoreStateV2")
        {
            var dict = new Dictionary<string, object>();
            dict["reader_handle"] = reader_handle;
            dict["state"] = state;
            var op = _op_def_lib._apply_op_helper("ReaderRestoreStateV2", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Produce a string tensor that encodes the state of a Reader.
        /// </summary>
        /// <param name="reader_handle">
        ///    Handle to a Reader.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReaderSerializeState'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Not all Readers support being serialized, so this can produce an
        ///    Unimplemented error.
        /// </remarks>
        public static Tensor reader_serialize_state (Tensor reader_handle, string name = "ReaderSerializeState")
        {
            var dict = new Dictionary<string, object>();
            dict["reader_handle"] = reader_handle;
            var op = _op_def_lib._apply_op_helper("ReaderSerializeState", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Produce a string tensor that encodes the state of a Reader.
        /// </summary>
        /// <param name="reader_handle">
        ///    Handle to a Reader.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReaderSerializeStateV2'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Not all Readers support being serialized, so this can produce an
        ///    Unimplemented error.
        /// </remarks>
        public static Tensor reader_serialize_state_v2 (Tensor reader_handle, string name = "ReaderSerializeStateV2")
        {
            var dict = new Dictionary<string, object>();
            dict["reader_handle"] = reader_handle;
            var op = _op_def_lib._apply_op_helper("ReaderSerializeStateV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the real part of a complex number.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Real'.
        /// </param>
        /// <param name="Tout">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given a tensor <c>input</c> of complex numbers, this operation returns a tensor of
        ///    type <c>float</c> that is the real part of each element in <c>input</c>. All elements in
        ///    <c>input</c> must be complex numbers of the form \\(a + bj\\), where *a* is the real
        ///    part returned by this operation and *b* is the imaginary part.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # tensor 'input' is [-2.25 + 4.75j, 3.25 + 5.75j]
        ///    tf.real(input) ==&amp;gt; [-2.25, 3.25]
        ///   </code>
        /// </remarks>
        public static Tensor real (Tensor input, TF_DataType? Tout = null, string name = "Real")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (Tout.HasValue)
                dict["Tout"] = Tout.Value;
            var op = _op_def_lib._apply_op_helper("Real", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns x / y element-wise for real types.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RealDiv'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    If <c>x</c> and <c>y</c> are reals, this will return the floating-point division.
        ///    
        ///    *NOTE*: <c>Div</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor real_div (Tensor x, Tensor y, string name = "RealDiv")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("RealDiv", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the reciprocal of x element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Reciprocal'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    I.e., \\(y = 1 / x\\).
        /// </remarks>
        public static Tensor reciprocal (Tensor x, string name = "Reciprocal")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Reciprocal", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradient for the inverse of <c>x</c> wrt its input.
        /// </summary>
        /// <param name="y">
        /// </param>
        /// <param name="dy">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReciprocalGrad'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Specifically, <c>grad = -dy * y*y</c>, where <c>y = 1/x</c>, and <c>dy</c>
        ///    is the corresponding input gradient.
        /// </remarks>
        public static Tensor reciprocal_grad (Tensor y, Tensor dy, string name = "ReciprocalGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["y"] = y;
            dict["dy"] = dy;
            var op = _op_def_lib._apply_op_helper("ReciprocalGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Emits randomized records.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RecordInput'.
        /// </param>
        /// <param name="file_pattern">
        ///    Optional argument
        ///    Glob pattern for the data files.
        /// </param>
        /// <param name="file_random_seed">
        ///    Random seeds used to produce randomized records.
        /// </param>
        /// <param name="file_shuffle_shift_ratio">
        ///    Shifts the list of files after the list is randomly
        ///    shuffled.
        /// </param>
        /// <param name="file_buffer_size">
        ///    The randomization shuffling buffer.
        /// </param>
        /// <param name="file_parallelism">
        ///    How many sstables are opened and concurrently iterated over.
        /// </param>
        /// <param name="batch_size">
        ///    The batch size.
        /// </param>
        /// <param name="compression_type">
        ///    The type of compression for the file. Currently ZLIB and
        ///    GZIP are supported. Defaults to none.
        /// </param>
        /// <returns>
        ///    A tensor of shape [batch_size].
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor record_input (string file_pattern, int? file_random_seed = null, float? file_shuffle_shift_ratio = null, int? file_buffer_size = null, int? file_parallelism = null, int? batch_size = null, string compression_type = null, string name = "RecordInput")
        {
            var dict = new Dictionary<string, object>();
            dict["file_pattern"] = file_pattern;
            if (file_random_seed.HasValue)
                dict["file_random_seed"] = file_random_seed.Value;
            if (file_shuffle_shift_ratio.HasValue)
                dict["file_shuffle_shift_ratio"] = file_shuffle_shift_ratio.Value;
            if (file_buffer_size.HasValue)
                dict["file_buffer_size"] = file_buffer_size.Value;
            if (file_parallelism.HasValue)
                dict["file_parallelism"] = file_parallelism.Value;
            if (batch_size.HasValue)
                dict["batch_size"] = batch_size.Value;
            if (compression_type != null)
                dict["compression_type"] = compression_type;
            var op = _op_def_lib._apply_op_helper("RecordInput", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Joins a string Tensor across the given dimensions.
        /// </summary>
        /// <param name="inputs">
        ///    The input to be joined.  All reduced indices must have non-zero size.
        /// </param>
        /// <param name="reduction_indices">
        ///    The dimensions to reduce over.  Dimensions are reduced in the
        ///    order specified.  Omitting <c>reduction_indices</c> is equivalent to passing
        ///    <c>[n-1, n-2, ..., 0]</c>.  Negative indices from <c>-n</c> to <c>-1</c> are supported.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReduceJoin'.
        /// </param>
        /// <param name="keep_dims">
        ///    If <c>True</c>, retain reduced dimensions with length <c>1</c>.
        /// </param>
        /// <param name="separator">
        ///    The separator to use when joining.
        /// </param>
        /// <returns>
        ///    Has shape equal to that of the input with reduced dimensions removed or
        ///    set to <c>1</c> depending on <c>keep_dims</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Computes the string join across dimensions in the given string Tensor of shape
        ///    <c>[\\(d_0, d_1, ..., d_{n-1}\\)]</c>.  Returns a new Tensor created by joining the input
        ///    strings with the given separator (default: empty string).  Negative indices are
        ///    counted backwards from the end, with <c>-1</c> being equivalent to <c>n - 1</c>.  If
        ///    indices are not specified, joins across all dimensions beginning from <c>n - 1</c>
        ///    through <c>0</c>.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # tensor <c>a</c> is [["a", "b"], ["c", "d"]]
        ///    tf.reduce_join(a, 0) ==&amp;gt; ["ac", "bd"]
        ///    tf.reduce_join(a, 1) ==&amp;gt; ["ab", "cd"]
        ///    tf.reduce_join(a, -2) = tf.reduce_join(a, 0) ==&amp;gt; ["ac", "bd"]
        ///    tf.reduce_join(a, -1) = tf.reduce_join(a, 1) ==&amp;gt; ["ab", "cd"]
        ///    tf.reduce_join(a, 0, keep_dims=True) ==&amp;gt; [["ac", "bd"]]
        ///    tf.reduce_join(a, 1, keep_dims=True) ==&amp;gt; [["ab"], ["cd"]]
        ///    tf.reduce_join(a, 0, separator=".") ==&amp;gt; ["a.c", "b.d"]
        ///    tf.reduce_join(a, [0, 1]) ==&amp;gt; "acbd"
        ///    tf.reduce_join(a, [1, 0]) ==&amp;gt; "abcd"
        ///    tf.reduce_join(a, []) ==&amp;gt; [["a", "b"], ["c", "d"]]
        ///    tf.reduce_join(a) = tf.reduce_join(a, [1, 0]) ==&amp;gt; "abcd"
        ///   </code>
        /// </remarks>
        public static Tensor reduce_join (Tensor inputs, Tensor reduction_indices, bool? keep_dims = null, string separator = null, string name = "ReduceJoin")
        {
            var dict = new Dictionary<string, object>();
            dict["inputs"] = inputs;
            dict["reduction_indices"] = reduction_indices;
            if (keep_dims.HasValue)
                dict["keep_dims"] = keep_dims.Value;
            if (separator != null)
                dict["separator"] = separator;
            var op = _op_def_lib._apply_op_helper("ReduceJoin", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates or finds a child frame, and makes <c>data</c> available to the child frame.
        /// </summary>
        /// <param name="data">
        ///    The tensor to be made available to the child frame.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RefEnter'.
        /// </param>
        /// <param name="frame_name">
        ///    Optional argument
        ///    The name of the child frame.
        /// </param>
        /// <param name="is_constant">
        ///    If true, the output is constant within the child frame.
        /// </param>
        /// <param name="parallel_iterations">
        ///    The number of iterations allowed to run in parallel.
        /// </param>
        /// <returns>
        ///    The same tensor as <c>data</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The unique <c>frame_name</c> is used by the <c>Executor</c> to identify frames. If
        ///    <c>is_constant</c> is true, <c>output</c> is a constant in the child frame; otherwise
        ///    it may be changed in the child frame. At most <c>parallel_iterations</c> iterations
        ///    are run in parallel in the child frame.
        /// </remarks>
        public static Tensor ref_enter (Tensor data, string frame_name, bool? is_constant = null, int? parallel_iterations = null, string name = "RefEnter")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            dict["frame_name"] = frame_name;
            if (is_constant.HasValue)
                dict["is_constant"] = is_constant.Value;
            if (parallel_iterations.HasValue)
                dict["parallel_iterations"] = parallel_iterations.Value;
            var op = _op_def_lib._apply_op_helper("RefEnter", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Exits the current frame to its parent frame.
        /// </summary>
        /// <param name="data">
        ///    The tensor to be made available to the parent frame.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RefExit'.
        /// </param>
        /// <returns>
        ///    The same tensor as <c>data</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Exit makes its input <c>data</c> available to the parent frame.
        /// </remarks>
        public static Tensor ref_exit (Tensor data, string name = "RefExit")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            var op = _op_def_lib._apply_op_helper("RefExit", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Return the same ref tensor as the input ref tensor.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RefIdentity'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor ref_identity (Tensor input, string name = "RefIdentity")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("RefIdentity", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Forwards the value of an available tensor from <c>inputs</c> to <c>output</c>.
        /// </summary>
        /// <param name="inputs">
        ///    The input tensors, exactly one of which will become available.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RefMerge'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output : Will be set to the available input tensor.
        ///    value_index : The index of the chosen input tensor in <c>inputs</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    <c>Merge</c> waits for at least one of the tensors in <c>inputs</c> to become available.
        ///    It is usually combined with <c>Switch</c> to implement branching.
        ///    
        ///    <c>Merge</c> forwards the first tensor for become available to <c>output</c>, and sets
        ///    <c>value_index</c> to its index in <c>inputs</c>.
        /// </remarks>
        public static (Tensor output, Tensor value_index) ref_merge (Tensor[] inputs, string name = "RefMerge")
        {
            var dict = new Dictionary<string, object>();
            dict["inputs"] = inputs;
            var op = _op_def_lib._apply_op_helper("RefMerge", name: name, keywords: dict);
            int _idx = 0;
            var output = op.outputs[_idx++];
            var value_index = op.outputs[_idx++];
            return (output, value_index);
        }

        /// <summary>
        ///    Makes its input available to the next iteration.
        /// </summary>
        /// <param name="data">
        ///    The tensor to be made available to the next iteration.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RefNextIteration'.
        /// </param>
        /// <returns>
        ///    The same tensor as <c>data</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor ref_next_iteration (Tensor data, string name = "RefNextIteration")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            var op = _op_def_lib._apply_op_helper("RefNextIteration", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Forwards the <c>index</c>th element of <c>inputs</c> to <c>output</c>.
        /// </summary>
        /// <param name="index">
        ///    A scalar that determines the input that gets selected.
        /// </param>
        /// <param name="inputs">
        ///    A list of ref tensors, one of which will be forwarded to <c>output</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RefSelect'.
        /// </param>
        /// <returns>
        ///    The forwarded tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor ref_select (Tensor index, Tensor[] inputs, string name = "RefSelect")
        {
            var dict = new Dictionary<string, object>();
            dict["index"] = index;
            dict["inputs"] = inputs;
            var op = _op_def_lib._apply_op_helper("RefSelect", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Forwards the ref tensor <c>data</c> to the output port determined by <c>pred</c>.
        /// </summary>
        /// <param name="data">
        ///    The ref tensor to be forwarded to the appropriate output.
        /// </param>
        /// <param name="pred">
        ///    A scalar that specifies which output port will receive data.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RefSwitch'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output_false : If <c>pred</c> is false, data will be forwarded to this output.
        ///    output_true : If <c>pred</c> is true, data will be forwarded to this output.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    If <c>pred</c> is true, the <c>data</c> input is forwarded to <c>output_true</c>. Otherwise,
        ///    the data goes to <c>output_false</c>.
        ///    
        ///    See also <c>Switch</c> and <c>Merge</c>.
        /// </remarks>
        public static (Tensor output_false, Tensor output_true) ref_switch (Tensor data, Tensor pred, string name = "RefSwitch")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            dict["pred"] = pred;
            var op = _op_def_lib._apply_op_helper("RefSwitch", name: name, keywords: dict);
            int _idx = 0;
            var output_false = op.outputs[_idx++];
            var output_true = op.outputs[_idx++];
            return (output_false, output_true);
        }

        /// <summary>
        ///    Check if the input matches the regex pattern.
        /// </summary>
        /// <param name="input">
        ///    A string tensor of the text to be processed.
        /// </param>
        /// <param name="pattern">
        ///    A scalar string tensor containing the regular expression to match the input.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RegexFullMatch'.
        /// </param>
        /// <returns>
        ///    A bool tensor with the same shape as <c>input</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The input is a string tensor of any shape. The pattern is a scalar
        ///    string tensor which is applied to every element of the input tensor.
        ///    The boolean values (True or False) of the output tensor indicate
        ///    if the input matches the regex pattern provided.
        ///    
        ///    The pattern follows the re2 syntax (https://github.com/google/re2/wiki/Syntax)
        /// </remarks>
        public static Tensor regex_full_match (Tensor input, Tensor pattern, string name = "RegexFullMatch")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["pattern"] = pattern;
            var op = _op_def_lib._apply_op_helper("RegexFullMatch", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Replaces the match of pattern in input with rewrite.
        /// </summary>
        /// <param name="input">
        ///    The text to be processed.
        /// </param>
        /// <param name="pattern">
        ///    The regular expression to match the input.
        /// </param>
        /// <param name="rewrite">
        ///    The rewrite to be applied to the matched expresion.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RegexReplace'.
        /// </param>
        /// <param name="replace_global">
        ///    If True, the replacement is global, otherwise the replacement
        ///    is done only on the first match.
        /// </param>
        /// <returns>
        ///    The text after applying pattern and rewrite.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    It follows the re2 syntax (https://github.com/google/re2/wiki/Syntax)
        /// </remarks>
        public static Tensor regex_replace (Tensor input, Tensor pattern, Tensor rewrite, bool? replace_global = null, string name = "RegexReplace")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["pattern"] = pattern;
            dict["rewrite"] = rewrite;
            if (replace_global.HasValue)
                dict["replace_global"] = replace_global.Value;
            var op = _op_def_lib._apply_op_helper("RegexReplace", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes rectified linear: <c>max(features, 0)</c>.
        /// </summary>
        /// <param name="features">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Relu'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor relu (Tensor features, string name = "Relu")
        {
            var dict = new Dictionary<string, object>();
            dict["features"] = features;
            var op = _op_def_lib._apply_op_helper("Relu", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes rectified linear 6: <c>min(max(features, 0), 6)</c>.
        /// </summary>
        /// <param name="features">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Relu6'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor relu6 (Tensor features, string name = "Relu6")
        {
            var dict = new Dictionary<string, object>();
            dict["features"] = features;
            var op = _op_def_lib._apply_op_helper("Relu6", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes rectified linear 6 gradients for a Relu6 operation.
        /// </summary>
        /// <param name="gradients">
        ///    The backpropagated gradients to the corresponding Relu6 operation.
        /// </param>
        /// <param name="features">
        ///    The features passed as input to the corresponding Relu6 operation, or
        ///    its output; using either one produces the same result.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Relu6Grad'.
        /// </param>
        /// <returns>
        ///    The gradients:
        ///    <c>gradients * (features &amp;gt; 0) * (features &amp;lt; 6)</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor relu6grad (Tensor gradients, Tensor features, string name = "Relu6Grad")
        {
            var dict = new Dictionary<string, object>();
            dict["gradients"] = gradients;
            dict["features"] = features;
            var op = _op_def_lib._apply_op_helper("Relu6Grad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes rectified linear gradients for a Relu operation.
        /// </summary>
        /// <param name="gradients">
        ///    The backpropagated gradients to the corresponding Relu operation.
        /// </param>
        /// <param name="features">
        ///    The features passed as input to the corresponding Relu operation, OR
        ///    the outputs of that operation (both work equivalently).
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReluGrad'.
        /// </param>
        /// <returns>
        ///    <c>gradients * (features &amp;gt; 0)</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor relu_grad (Tensor gradients, Tensor features, string name = "ReluGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["gradients"] = gradients;
            dict["features"] = features;
            var op = _op_def_lib._apply_op_helper("ReluGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Execute a sub graph on a remote processor.
        /// </summary>
        /// <param name="inputs">
        ///    Arbitrary number of tensors with arbitrary data types
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RemoteFusedGraphExecute'.
        /// </param>
        /// <param name="Toutputs">
        ///    Optional argument
        /// </param>
        /// <param name="serialized_remote_fused_graph_execute_info">
        ///    Optional argument
        ///    Serialized protocol buffer
        ///    of RemoteFusedGraphExecuteInfo which contains graph specifications.
        /// </param>
        /// <returns>
        ///    Arbitrary number of tensors with arbitrary data types
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The graph specifications(such as graph itself, input tensors and output names)
        ///    are stored as a serialized protocol buffer of RemoteFusedGraphExecuteInfo
        ///    as serialized_remote_fused_graph_execute_info.
        ///    The specifications will be passed to a dedicated registered
        ///    remote fused graph executor.  The executor will send the graph specifications
        ///    to a remote processor and execute that graph.  The execution results
        ///    will be passed to consumer nodes as outputs of this node.
        /// </remarks>
        public static Tensor[] remote_fused_graph_execute (Tensor[] inputs, TF_DataType[] Toutputs, string serialized_remote_fused_graph_execute_info, string name = "RemoteFusedGraphExecute")
        {
            var dict = new Dictionary<string, object>();
            dict["inputs"] = inputs;
            dict["Toutputs"] = Toutputs;
            dict["serialized_remote_fused_graph_execute_info"] = serialized_remote_fused_graph_execute_info;
            var op = _op_def_lib._apply_op_helper("RemoteFusedGraphExecute", name: name, keywords: dict);
            int _idx = 0;
            var outputs = Enumerable.Range(0, op.OutputListLength("outputs")).Select(_ => op.outputs[_idx++]).ToArray();
            return (outputs);
        }

        /// <summary>
        ///    Creates a dataset that emits the outputs of <c>input_dataset</c> <c>count</c> times.
        /// </summary>
        /// <param name="input_dataset">
        /// </param>
        /// <param name="count">
        ///    A scalar representing the number of times that <c>input_dataset</c> should
        ///    be repeated. A value of <c>-1</c> indicates that it should be repeated infinitely.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RepeatDataset'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor repeat_dataset (Tensor input_dataset, Tensor count, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "RepeatDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["count"] = count;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("RepeatDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Given a quantized tensor described by (input, input_min, input_max), outputs a
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="input_min">
        ///    The float value that the minimum quantized input value represents.
        /// </param>
        /// <param name="input_max">
        ///    The float value that the maximum quantized input value represents.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RequantizationRange'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output_min : The computed min output.
        ///    output_max : the computed max output.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    range that covers the actual values present in that tensor.  This op is
        ///    typically used to produce the requested_output_min and requested_output_max for
        ///    Requantize.
        /// </remarks>
        public static (Tensor output_min, Tensor output_max) requantization_range (Tensor input, Tensor input_min, Tensor input_max, string name = "RequantizationRange")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["input_min"] = input_min;
            dict["input_max"] = input_max;
            var op = _op_def_lib._apply_op_helper("RequantizationRange", name: name, keywords: dict);
            int _idx = 0;
            var output_min = op.outputs[_idx++];
            var output_max = op.outputs[_idx++];
            return (output_min, output_max);
        }

        /// <summary>
        ///    Convert the quantized 'input' tensor into a lower-precision 'output', using the
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="input_min">
        ///    The float value that the minimum quantized input value represents.
        /// </param>
        /// <param name="input_max">
        ///    The float value that the maximum quantized input value represents.
        /// </param>
        /// <param name="requested_output_min">
        ///    The float value that the minimum quantized output value represents.
        /// </param>
        /// <param name="requested_output_max">
        ///    The float value that the maximum quantized output value represents.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Requantize'.
        /// </param>
        /// <param name="out_type">
        ///    Optional argument
        ///    The type of the output. Should be a lower bit depth than Tinput.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output :
        ///    output_min : The requested_output_min value is copied into this output.
        ///    output_max : The requested_output_max value is copied into this output.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    output range specified with 'requested_output_min' and 'requested_output_max'.
        ///    
        ///    [input_min, input_max] are scalar floats that specify the range for the float
        ///    interpretation of the 'input' data. For example, if input_min is -1.0f and
        ///    input_max is 1.0f, and we are dealing with quint16 quantized data, then a 0
        ///    value in the 16-bit data should be interpreted as -1.0f, and a 65535 means 1.0f.
        /// </remarks>
        public static (Tensor output, Tensor output_min, Tensor output_max) requantize (Tensor input, Tensor input_min, Tensor input_max, Tensor requested_output_min, Tensor requested_output_max, TF_DataType out_type, string name = "Requantize")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["input_min"] = input_min;
            dict["input_max"] = input_max;
            dict["requested_output_min"] = requested_output_min;
            dict["requested_output_max"] = requested_output_max;
            dict["out_type"] = out_type;
            var op = _op_def_lib._apply_op_helper("Requantize", name: name, keywords: dict);
            int _idx = 0;
            var output = op.outputs[_idx++];
            var output_min = op.outputs[_idx++];
            var output_max = op.outputs[_idx++];
            return (output, output_min, output_max);
        }

        /// <summary>
        ///    Reshapes a tensor.
        /// </summary>
        /// <param name="tensor">
        /// </param>
        /// <param name="shape">
        ///    Defines the shape of the output tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Reshape'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given <c>tensor</c>, this operation returns a tensor that has the same values
        ///    as <c>tensor</c> with shape <c>shape</c>.
        ///    
        ///    If one component of <c>shape</c> is the special value -1, the size of that dimension
        ///    is computed so that the total size remains constant.  In particular, a <c>shape</c>
        ///    of <c>[-1]</c> flattens into 1-D.  At most one component of <c>shape</c> can be -1.
        ///    
        ///    If <c>shape</c> is 1-D or higher, then the operation returns a tensor with shape
        ///    <c>shape</c> filled with the values of <c>tensor</c>. In this case, the number of elements
        ///    implied by <c>shape</c> must be the same as the number of elements in <c>tensor</c>.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # tensor 't' is [1, 2, 3, 4, 5, 6, 7, 8, 9]
        ///    # tensor 't' has shape [9]
        ///    reshape(t, [3, 3]) ==&amp;gt; [[1, 2, 3],
        ///    [4, 5, 6],
        ///    [7, 8, 9]]
        ///    
        ///    # tensor 't' is [[[1, 1], [2, 2]],
        ///    #                [[3, 3], [4, 4]]]
        ///    # tensor 't' has shape [2, 2, 2]
        ///    reshape(t, [2, 4]) ==&amp;gt; [[1, 1, 2, 2],
        ///    [3, 3, 4, 4]]
        ///    
        ///    # tensor 't' is [[[1, 1, 1],
        ///    #                 [2, 2, 2]],
        ///    #                [[3, 3, 3],
        ///    #                 [4, 4, 4]],
        ///    #                [[5, 5, 5],
        ///    #                 [6, 6, 6]]]
        ///    # tensor 't' has shape [3, 2, 3]
        ///    # pass '[-1]' to flatten 't'
        ///    reshape(t, [-1]) ==&amp;gt; [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6]
        ///    
        ///    # -1 can also be used to infer the shape
        ///    
        ///    # -1 is inferred to be 9:
        ///    reshape(t, [2, -1]) ==&amp;gt; [[1, 1, 1, 2, 2, 2, 3, 3, 3],
        ///    [4, 4, 4, 5, 5, 5, 6, 6, 6]]
        ///    # -1 is inferred to be 2:
        ///    reshape(t, [-1, 9]) ==&amp;gt; [[1, 1, 1, 2, 2, 2, 3, 3, 3],
        ///    [4, 4, 4, 5, 5, 5, 6, 6, 6]]
        ///    # -1 is inferred to be 3:
        ///    reshape(t, [ 2, -1, 3]) ==&amp;gt; [[[1, 1, 1],
        ///    [2, 2, 2],
        ///    [3, 3, 3]],
        ///    [[4, 4, 4],
        ///    [5, 5, 5],
        ///    [6, 6, 6]]]
        ///    
        ///    # tensor 't' is [7]
        ///    # shape <c>[]</c> reshapes to a scalar
        ///    reshape(t, []) ==&amp;gt; 7
        ///   </code>
        /// </remarks>
        public static Tensor reshape (Tensor tensor, Tensor shape, string name = "Reshape")
        {
            var dict = new Dictionary<string, object>();
            dict["tensor"] = tensor;
            dict["shape"] = shape;
            var op = _op_def_lib._apply_op_helper("Reshape", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Resize <c>images</c> to <c>size</c> using area interpolation.
        /// </summary>
        /// <param name="images">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.
        /// </param>
        /// <param name="size">
        ///    = A 1-D int32 Tensor of 2 elements: <c>new_height, new_width</c>.  The
        ///    new size for the images.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResizeArea'.
        /// </param>
        /// <param name="align_corners">
        ///    If true, the centers of the 4 corner pixels of the input and output tensors are
        ///    aligned, preserving the values at the corner pixels. Defaults to false.
        /// </param>
        /// <returns>
        ///    4-D with shape
        ///    <c>[batch, new_height, new_width, channels]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Input images can be of different types but output images are always float.
        ///    
        ///    The range of pixel values for the output image might be slightly different
        ///    from the range for the input image because of limited numerical precision.
        ///    To guarantee an output range, for example <c>[0.0, 1.0]</c>, apply
        ///    <c>tf.clip_by_value</c> to the output.
        ///    
        ///    Each output pixel is computed by first transforming the pixel's footprint into
        ///    the input tensor and then averaging the pixels that intersect the footprint. An
        ///    input pixel's contribution to the average is weighted by the fraction of its
        ///    area that intersects the footprint.  This is the same as OpenCV's INTER_AREA.
        /// </remarks>
        public static Tensor resize_area (Tensor images, Tensor size, bool? align_corners = null, string name = "ResizeArea")
        {
            var dict = new Dictionary<string, object>();
            dict["images"] = images;
            dict["size"] = size;
            if (align_corners.HasValue)
                dict["align_corners"] = align_corners.Value;
            var op = _op_def_lib._apply_op_helper("ResizeArea", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Resize <c>images</c> to <c>size</c> using bicubic interpolation.
        /// </summary>
        /// <param name="images">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.
        /// </param>
        /// <param name="size">
        ///    = A 1-D int32 Tensor of 2 elements: <c>new_height, new_width</c>.  The
        ///    new size for the images.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResizeBicubic'.
        /// </param>
        /// <param name="align_corners">
        ///    If true, the centers of the 4 corner pixels of the input and output tensors are
        ///    aligned, preserving the values at the corner pixels. Defaults to false.
        /// </param>
        /// <returns>
        ///    4-D with shape
        ///    <c>[batch, new_height, new_width, channels]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Input images can be of different types but output images are always float.
        /// </remarks>
        public static Tensor resize_bicubic (Tensor images, Tensor size, bool? align_corners = null, string name = "ResizeBicubic")
        {
            var dict = new Dictionary<string, object>();
            dict["images"] = images;
            dict["size"] = size;
            if (align_corners.HasValue)
                dict["align_corners"] = align_corners.Value;
            var op = _op_def_lib._apply_op_helper("ResizeBicubic", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradient of bicubic interpolation.
        /// </summary>
        /// <param name="grads">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.
        /// </param>
        /// <param name="original_image">
        ///    4-D with shape <c>[batch, orig_height, orig_width, channels]</c>,
        ///    The image tensor that was resized.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResizeBicubicGrad'.
        /// </param>
        /// <param name="align_corners">
        ///    If true, the centers of the 4 corner pixels of the input and grad tensors are
        ///    aligned. Defaults to false.
        /// </param>
        /// <returns>
        ///    4-D with shape <c>[batch, orig_height, orig_width, channels]</c>.
        ///    Gradients with respect to the input image. Input image must have been
        ///    float or double.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor resize_bicubic_grad (Tensor grads, Tensor original_image, bool? align_corners = null, string name = "ResizeBicubicGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["grads"] = grads;
            dict["original_image"] = original_image;
            if (align_corners.HasValue)
                dict["align_corners"] = align_corners.Value;
            var op = _op_def_lib._apply_op_helper("ResizeBicubicGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Resize <c>images</c> to <c>size</c> using bilinear interpolation.
        /// </summary>
        /// <param name="images">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.
        /// </param>
        /// <param name="size">
        ///    = A 1-D int32 Tensor of 2 elements: <c>new_height, new_width</c>.  The
        ///    new size for the images.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResizeBilinear'.
        /// </param>
        /// <param name="align_corners">
        ///    If true, the centers of the 4 corner pixels of the input and output tensors are
        ///    aligned, preserving the values at the corner pixels. Defaults to false.
        /// </param>
        /// <returns>
        ///    4-D with shape
        ///    <c>[batch, new_height, new_width, channels]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Input images can be of different types but output images are always float.
        /// </remarks>
        public static Tensor resize_bilinear (Tensor images, Tensor size, bool? align_corners = null, string name = "ResizeBilinear")
        {
            var dict = new Dictionary<string, object>();
            dict["images"] = images;
            dict["size"] = size;
            if (align_corners.HasValue)
                dict["align_corners"] = align_corners.Value;
            var op = _op_def_lib._apply_op_helper("ResizeBilinear", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradient of bilinear interpolation.
        /// </summary>
        /// <param name="grads">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.
        /// </param>
        /// <param name="original_image">
        ///    4-D with shape <c>[batch, orig_height, orig_width, channels]</c>,
        ///    The image tensor that was resized.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResizeBilinearGrad'.
        /// </param>
        /// <param name="align_corners">
        ///    If true, the centers of the 4 corner pixels of the input and grad tensors are
        ///    aligned. Defaults to false.
        /// </param>
        /// <returns>
        ///    4-D with shape <c>[batch, orig_height, orig_width, channels]</c>.
        ///    Gradients with respect to the input image. Input image must have been
        ///    float or double.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor resize_bilinear_grad (Tensor grads, Tensor original_image, bool? align_corners = null, string name = "ResizeBilinearGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["grads"] = grads;
            dict["original_image"] = original_image;
            if (align_corners.HasValue)
                dict["align_corners"] = align_corners.Value;
            var op = _op_def_lib._apply_op_helper("ResizeBilinearGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Resize <c>images</c> to <c>size</c> using nearest neighbor interpolation.
        /// </summary>
        /// <param name="images">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.
        /// </param>
        /// <param name="size">
        ///    = A 1-D int32 Tensor of 2 elements: <c>new_height, new_width</c>.  The
        ///    new size for the images.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResizeNearestNeighbor'.
        /// </param>
        /// <param name="align_corners">
        ///    If true, the centers of the 4 corner pixels of the input and output tensors are
        ///    aligned, preserving the values at the corner pixels. Defaults to false.
        /// </param>
        /// <returns>
        ///    4-D with shape
        ///    <c>[batch, new_height, new_width, channels]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor resize_nearest_neighbor (Tensor images, Tensor size, bool? align_corners = null, string name = "ResizeNearestNeighbor")
        {
            var dict = new Dictionary<string, object>();
            dict["images"] = images;
            dict["size"] = size;
            if (align_corners.HasValue)
                dict["align_corners"] = align_corners.Value;
            var op = _op_def_lib._apply_op_helper("ResizeNearestNeighbor", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradient of nearest neighbor interpolation.
        /// </summary>
        /// <param name="grads">
        ///    4-D with shape <c>[batch, height, width, channels]</c>.
        /// </param>
        /// <param name="size">
        ///    = A 1-D int32 Tensor of 2 elements: <c>orig_height, orig_width</c>. The
        ///    original input size.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResizeNearestNeighborGrad'.
        /// </param>
        /// <param name="align_corners">
        ///    If true, the centers of the 4 corner pixels of the input and grad tensors are
        ///    aligned. Defaults to false.
        /// </param>
        /// <returns>
        ///    4-D with shape <c>[batch, orig_height, orig_width, channels]</c>. Gradients
        ///    with respect to the input image.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor resize_nearest_neighbor_grad (Tensor grads, Tensor size, bool? align_corners = null, string name = "ResizeNearestNeighborGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["grads"] = grads;
            dict["size"] = size;
            if (align_corners.HasValue)
                dict["align_corners"] = align_corners.Value;
            var op = _op_def_lib._apply_op_helper("ResizeNearestNeighborGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update '*var' according to the AdaMax algorithm.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="m">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="v">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="beta1_power">
        ///    Must be a scalar.
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="beta1">
        ///    Momentum factor. Must be a scalar.
        /// </param>
        /// <param name="beta2">
        ///    Momentum factor. Must be a scalar.
        /// </param>
        /// <param name="epsilon">
        ///    Ridge term. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceApplyAdaMax'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var, m, and v tensors will be protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    m_t &amp;lt;- beta1 * m_{t-1} + (1 - beta1) * g
        ///    v_t &amp;lt;- max(beta2 * v_{t-1}, abs(g))
        ///    variable &amp;lt;- variable - learning_rate / (1 - beta1^t) * m_t / (v_t + epsilon)
        /// </remarks>
        public static Operation resource_apply_ada_max (Tensor var, Tensor m, Tensor v, Tensor beta1_power, Tensor lr, Tensor beta1, Tensor beta2, Tensor epsilon, Tensor grad, bool? use_locking = null, string name = "ResourceApplyAdaMax")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["m"] = m;
            dict["v"] = v;
            dict["beta1_power"] = beta1_power;
            dict["lr"] = lr;
            dict["beta1"] = beta1;
            dict["beta2"] = beta2;
            dict["epsilon"] = epsilon;
            dict["grad"] = grad;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceApplyAdaMax", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update '*var' according to the adadelta scheme.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum_update">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="rho">
        ///    Decay factor. Must be a scalar.
        /// </param>
        /// <param name="epsilon">
        ///    Constant factor. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceApplyAdadelta'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, updating of the var, accum and update_accum tensors will be protected by
        ///    a lock; otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    accum = rho() * accum + (1 - rho()) * grad.square();
        ///    update = (update_accum + epsilon).sqrt() * (accum + epsilon()).rsqrt() * grad;
        ///    update_accum = rho() * update_accum + (1 - rho()) * update.square();
        ///    var -= update;
        /// </remarks>
        public static Operation resource_apply_adadelta (Tensor var, Tensor accum, Tensor accum_update, Tensor lr, Tensor rho, Tensor epsilon, Tensor grad, bool? use_locking = null, string name = "ResourceApplyAdadelta")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["accum_update"] = accum_update;
            dict["lr"] = lr;
            dict["rho"] = rho;
            dict["epsilon"] = epsilon;
            dict["grad"] = grad;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceApplyAdadelta", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update '*var' according to the adagrad scheme.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceApplyAdagrad'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var and accum tensors will be protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <param name="update_slots">
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    accum += grad * grad
        ///    var -= lr * grad * (1 / sqrt(accum))
        /// </remarks>
        public static Operation resource_apply_adagrad (Tensor var, Tensor accum, Tensor lr, Tensor grad, bool? use_locking = null, bool? update_slots = null, string name = "ResourceApplyAdagrad")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["lr"] = lr;
            dict["grad"] = grad;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            if (update_slots.HasValue)
                dict["update_slots"] = update_slots.Value;
            var op = _op_def_lib._apply_op_helper("ResourceApplyAdagrad", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update '*var' according to the proximal adagrad scheme.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="gradient_accumulator">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="gradient_squared_accumulator">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="l1">
        ///    L1 regularization. Must be a scalar.
        /// </param>
        /// <param name="l2">
        ///    L2 regularization. Must be a scalar.
        /// </param>
        /// <param name="global_step">
        ///    Training step number. Must be a scalar.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceApplyAdagradDA'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, updating of the var and accum tensors will be protected by
        ///    a lock; otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation resource_apply_adagrad_d_a (Tensor var, Tensor gradient_accumulator, Tensor gradient_squared_accumulator, Tensor grad, Tensor lr, Tensor l1, Tensor l2, Tensor global_step, bool? use_locking = null, string name = "ResourceApplyAdagradDA")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["gradient_accumulator"] = gradient_accumulator;
            dict["gradient_squared_accumulator"] = gradient_squared_accumulator;
            dict["grad"] = grad;
            dict["lr"] = lr;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["global_step"] = global_step;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceApplyAdagradDA", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update '*var' according to the Adam algorithm.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="m">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="v">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="beta1_power">
        ///    Must be a scalar.
        /// </param>
        /// <param name="beta2_power">
        ///    Must be a scalar.
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="beta1">
        ///    Momentum factor. Must be a scalar.
        /// </param>
        /// <param name="beta2">
        ///    Momentum factor. Must be a scalar.
        /// </param>
        /// <param name="epsilon">
        ///    Ridge term. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceApplyAdam'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var, m, and v tensors will be protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <param name="use_nesterov">
        ///    If <c>True</c>, uses the nesterov update.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    $$lr_t := \text{learning\_rate} * \sqrt{1 - beta_2^t} / (1 - beta_1^t)$$
        ///    $$m_t := beta_1 * m_{t-1} + (1 - beta_1) * g$$
        ///    $$v_t := beta_2 * v_{t-1} + (1 - beta_2) * g * g$$
        ///    $$variable := variable - lr_t * m_t / (\sqrt{v_t} + \epsilon)$$
        /// </remarks>
        public static Operation resource_apply_adam (Tensor var, Tensor m, Tensor v, Tensor beta1_power, Tensor beta2_power, Tensor lr, Tensor beta1, Tensor beta2, Tensor epsilon, Tensor grad, bool? use_locking = null, bool? use_nesterov = null, string name = "ResourceApplyAdam")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["m"] = m;
            dict["v"] = v;
            dict["beta1_power"] = beta1_power;
            dict["beta2_power"] = beta2_power;
            dict["lr"] = lr;
            dict["beta1"] = beta1;
            dict["beta2"] = beta2;
            dict["epsilon"] = epsilon;
            dict["grad"] = grad;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            if (use_nesterov.HasValue)
                dict["use_nesterov"] = use_nesterov.Value;
            var op = _op_def_lib._apply_op_helper("ResourceApplyAdam", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update '*var' according to the AddSign update.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="m">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="alpha">
        ///    Must be a scalar.
        /// </param>
        /// <param name="sign_decay">
        ///    Must be a scalar.
        /// </param>
        /// <param name="beta">
        ///    Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceApplyAddSign'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var and m tensors is
        ///    protected by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    m_t &amp;lt;- beta1 * m_{t-1} + (1 - beta1) * g
        ///    update &amp;lt;- (alpha + sign_decay * sign(g) *sign(m)) * g
        ///    variable &amp;lt;- variable - lr_t * update
        /// </remarks>
        public static Operation resource_apply_add_sign (Tensor var, Tensor m, Tensor lr, Tensor alpha, Tensor sign_decay, Tensor beta, Tensor grad, bool? use_locking = null, string name = "ResourceApplyAddSign")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["m"] = m;
            dict["lr"] = lr;
            dict["alpha"] = alpha;
            dict["sign_decay"] = sign_decay;
            dict["beta"] = beta;
            dict["grad"] = grad;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceApplyAddSign", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update '*var' according to the centered RMSProp algorithm.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="mg">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="ms">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="mom">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="rho">
        ///    Decay rate. Must be a scalar.
        /// </param>
        /// <param name="momentum">
        /// </param>
        /// <param name="epsilon">
        ///    Ridge term. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceApplyCenteredRMSProp'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var, mg, ms, and mom tensors is
        ///    protected by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    The centered RMSProp algorithm uses an estimate of the centered second moment
        ///    (i.e., the variance) for normalization, as opposed to regular RMSProp, which
        ///    uses the (uncentered) second moment. This often helps with training, but is
        ///    slightly more expensive in terms of computation and memory.
        ///    
        ///    Note that in dense implementation of this algorithm, mg, ms, and mom will
        ///    update even if the grad is zero, but in this sparse implementation, mg, ms,
        ///    and mom will not update in iterations during which the grad is zero.
        ///    
        ///    mean_square = decay * mean_square + (1-decay) * gradient ** 2
        ///    mean_grad = decay * mean_grad + (1-decay) * gradient
        ///    
        ///    Delta = learning_rate * gradient / sqrt(mean_square + epsilon - mean_grad ** 2)
        ///    
        ///    mg &amp;lt;- rho * mg_{t-1} + (1-rho) * grad
        ///    ms &amp;lt;- rho * ms_{t-1} + (1-rho) * grad * grad
        ///    mom &amp;lt;- momentum * mom_{t-1} + lr * grad / sqrt(ms - mg * mg + epsilon)
        ///    var &amp;lt;- var - mom
        /// </remarks>
        public static Operation resource_apply_centered_r_m_s_prop (Tensor var, Tensor mg, Tensor ms, Tensor mom, Tensor lr, Tensor rho, Tensor momentum, Tensor epsilon, Tensor grad, bool? use_locking = null, string name = "ResourceApplyCenteredRMSProp")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["mg"] = mg;
            dict["ms"] = ms;
            dict["mom"] = mom;
            dict["lr"] = lr;
            dict["rho"] = rho;
            dict["momentum"] = momentum;
            dict["epsilon"] = epsilon;
            dict["grad"] = grad;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceApplyCenteredRMSProp", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update '*var' according to the Ftrl-proximal scheme.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="linear">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="l1">
        ///    L1 regulariation. Must be a scalar.
        /// </param>
        /// <param name="l2">
        ///    L2 regulariation. Must be a scalar.
        /// </param>
        /// <param name="lr_power">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceApplyFtrl'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var and accum tensors will be protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    accum_new = accum + grad * grad
        ///    linear += grad - (accum_new^(-lr_power) - accum^(-lr_power)) / lr * var
        ///    quadratic = 1.0 / (accum_new^(lr_power) * lr) + 2 * l2
        ///    var = (sign(linear) * l1 - linear) / quadratic if |linear| &amp;gt; l1 else 0.0
        ///    accum = accum_new
        /// </remarks>
        public static Operation resource_apply_ftrl (Tensor var, Tensor accum, Tensor linear, Tensor grad, Tensor lr, Tensor l1, Tensor l2, Tensor lr_power, bool? use_locking = null, string name = "ResourceApplyFtrl")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["linear"] = linear;
            dict["grad"] = grad;
            dict["lr"] = lr;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["lr_power"] = lr_power;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceApplyFtrl", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update '*var' according to the Ftrl-proximal scheme.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="linear">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="l1">
        ///    L1 regulariation. Must be a scalar.
        /// </param>
        /// <param name="l2">
        ///    L2 shrinkage regulariation. Must be a scalar.
        /// </param>
        /// <param name="l2_shrinkage">
        /// </param>
        /// <param name="lr_power">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceApplyFtrlV2'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var and accum tensors will be protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    grad_with_shrinkage = grad + 2 * l2_shrinkage * var
        ///    accum_new = accum + grad_with_shrinkage * grad_with_shrinkage
        ///    linear += grad_with_shrinkage +
        ///    (accum_new^(-lr_power) - accum^(-lr_power)) / lr * var
        ///    quadratic = 1.0 / (accum_new^(lr_power) * lr) + 2 * l2
        ///    var = (sign(linear) * l1 - linear) / quadratic if |linear| &amp;gt; l1 else 0.0
        ///    accum = accum_new
        /// </remarks>
        public static Operation resource_apply_ftrl_v2 (Tensor var, Tensor accum, Tensor linear, Tensor grad, Tensor lr, Tensor l1, Tensor l2, Tensor l2_shrinkage, Tensor lr_power, bool? use_locking = null, string name = "ResourceApplyFtrlV2")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["linear"] = linear;
            dict["grad"] = grad;
            dict["lr"] = lr;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["l2_shrinkage"] = l2_shrinkage;
            dict["lr_power"] = lr_power;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceApplyFtrlV2", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update '*var' by subtracting 'alpha' * 'delta' from it.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="alpha">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="delta">
        ///    The change.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceApplyGradientDescent'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, the subtraction will be protected by a lock;
        ///    otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation resource_apply_gradient_descent (Tensor var, Tensor alpha, Tensor delta, bool? use_locking = null, string name = "ResourceApplyGradientDescent")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["alpha"] = alpha;
            dict["delta"] = delta;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceApplyGradientDescent", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update '*var' according to the momentum scheme. Set use_nesterov = True if you
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="momentum">
        ///    Momentum. Must be a scalar.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceApplyMomentum'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var and accum tensors will be protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <param name="use_nesterov">
        ///    If <c>True</c>, the tensor passed to compute grad will be
        ///    var - lr * momentum * accum, so in the end, the var you get is actually
        ///    var - lr * momentum * accum.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    want to use Nesterov momentum.
        ///    
        ///    accum = accum * momentum + grad
        ///    var -= lr * accum
        /// </remarks>
        public static Operation resource_apply_momentum (Tensor var, Tensor accum, Tensor lr, Tensor grad, Tensor momentum, bool? use_locking = null, bool? use_nesterov = null, string name = "ResourceApplyMomentum")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["lr"] = lr;
            dict["grad"] = grad;
            dict["momentum"] = momentum;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            if (use_nesterov.HasValue)
                dict["use_nesterov"] = use_nesterov.Value;
            var op = _op_def_lib._apply_op_helper("ResourceApplyMomentum", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update '*var' according to the AddSign update.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="m">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="logbase">
        ///    Must be a scalar.
        /// </param>
        /// <param name="sign_decay">
        ///    Must be a scalar.
        /// </param>
        /// <param name="beta">
        ///    Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceApplyPowerSign'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var and m tensors is
        ///    protected by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    m_t &amp;lt;- beta1 * m_{t-1} + (1 - beta1) * g
        ///    update &amp;lt;- exp(logbase * sign_decay * sign(g) * sign(m_t)) * g
        ///    variable &amp;lt;- variable - lr_t * update
        /// </remarks>
        public static Operation resource_apply_power_sign (Tensor var, Tensor m, Tensor lr, Tensor logbase, Tensor sign_decay, Tensor beta, Tensor grad, bool? use_locking = null, string name = "ResourceApplyPowerSign")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["m"] = m;
            dict["lr"] = lr;
            dict["logbase"] = logbase;
            dict["sign_decay"] = sign_decay;
            dict["beta"] = beta;
            dict["grad"] = grad;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceApplyPowerSign", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update '*var' and '*accum' according to FOBOS with Adagrad learning rate.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="l1">
        ///    L1 regularization. Must be a scalar.
        /// </param>
        /// <param name="l2">
        ///    L2 regularization. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceApplyProximalAdagrad'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, updating of the var and accum tensors will be protected by
        ///    a lock; otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    accum += grad * grad
        ///    prox_v = var - lr * grad * (1 / sqrt(accum))
        ///    var = sign(prox_v)/(1+lr*l2) * max{|prox_v|-lr*l1,0}
        /// </remarks>
        public static Operation resource_apply_proximal_adagrad (Tensor var, Tensor accum, Tensor lr, Tensor l1, Tensor l2, Tensor grad, bool? use_locking = null, string name = "ResourceApplyProximalAdagrad")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["lr"] = lr;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["grad"] = grad;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceApplyProximalAdagrad", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update '*var' as FOBOS algorithm with fixed learning rate.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="alpha">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="l1">
        ///    L1 regularization. Must be a scalar.
        /// </param>
        /// <param name="l2">
        ///    L2 regularization. Must be a scalar.
        /// </param>
        /// <param name="delta">
        ///    The change.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceApplyProximalGradientDescent'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, the subtraction will be protected by a lock;
        ///    otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    prox_v = var - alpha * delta
        ///    var = sign(prox_v)/(1+alpha*l2) * max{|prox_v|-alpha*l1,0}
        /// </remarks>
        public static Operation resource_apply_proximal_gradient_descent (Tensor var, Tensor alpha, Tensor l1, Tensor l2, Tensor delta, bool? use_locking = null, string name = "ResourceApplyProximalGradientDescent")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["alpha"] = alpha;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["delta"] = delta;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceApplyProximalGradientDescent", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update '*var' according to the RMSProp algorithm.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="ms">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="mom">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="rho">
        ///    Decay rate. Must be a scalar.
        /// </param>
        /// <param name="momentum">
        /// </param>
        /// <param name="epsilon">
        ///    Ridge term. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceApplyRMSProp'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var, ms, and mom tensors is protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    Note that in dense implementation of this algorithm, ms and mom will
        ///    update even if the grad is zero, but in this sparse implementation, ms
        ///    and mom will not update in iterations during which the grad is zero.
        ///    
        ///    mean_square = decay * mean_square + (1-decay) * gradient ** 2
        ///    Delta = learning_rate * gradient / sqrt(mean_square + epsilon)
        ///    
        ///    ms &amp;lt;- rho * ms_{t-1} + (1-rho) * grad * grad
        ///    mom &amp;lt;- momentum * mom_{t-1} + lr * grad / sqrt(ms + epsilon)
        ///    var &amp;lt;- var - mom
        /// </remarks>
        public static Operation resource_apply_r_m_s_prop (Tensor var, Tensor ms, Tensor mom, Tensor lr, Tensor rho, Tensor momentum, Tensor epsilon, Tensor grad, bool? use_locking = null, string name = "ResourceApplyRMSProp")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["ms"] = ms;
            dict["mom"] = mom;
            dict["lr"] = lr;
            dict["rho"] = rho;
            dict["momentum"] = momentum;
            dict["epsilon"] = epsilon;
            dict["grad"] = grad;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceApplyRMSProp", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Increments variable pointed to by 'resource' until it reaches 'limit'.
        /// </summary>
        /// <param name="resource">
        ///    Should be from a scalar <c>Variable</c> node.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceCountUpTo'.
        /// </param>
        /// <param name="limit">
        ///    Optional argument
        ///    If incrementing ref would bring it above limit, instead generates an
        ///    'OutOfRange' error.
        /// </param>
        /// <param name="T">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    A copy of the input before increment. If nothing else modifies the
        ///    input, the values produced will all be distinct.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor resource_count_up_to (Tensor resource, int limit, TF_DataType T, string name = "ResourceCountUpTo")
        {
            var dict = new Dictionary<string, object>();
            dict["resource"] = resource;
            dict["limit"] = limit;
            dict["T"] = T;
            var op = _op_def_lib._apply_op_helper("ResourceCountUpTo", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Gather slices from the variable pointed to by <c>resource</c> according to <c>indices</c>.
        /// </summary>
        /// <param name="resource">
        /// </param>
        /// <param name="indices">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceGather'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        /// </param>
        /// <param name="validate_indices">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    <c>indices</c> must be an integer tensor of any dimension (usually 0-D or 1-D).
        ///    Produces an output tensor with shape <c>indices.shape + params.shape[1:]</c> where:
        ///    
        ///   <code>
        ///    # Scalar indices
        ///    output[:, ..., :] = params[indices, :, ... :]
        ///    
        ///    # Vector indices
        ///    output[i, :, ..., :] = params[indices[i], :, ... :]
        ///    
        ///    # Higher rank indices
        ///    output[i, ..., j, :, ... :] = params[indices[i, ..., j], :, ..., :]
        ///   </code>
        /// </remarks>
        public static Tensor resource_gather (Tensor resource, Tensor indices, TF_DataType dtype, bool? validate_indices = null, string name = "ResourceGather")
        {
            var dict = new Dictionary<string, object>();
            dict["resource"] = resource;
            dict["indices"] = indices;
            dict["dtype"] = dtype;
            if (validate_indices.HasValue)
                dict["validate_indices"] = validate_indices.Value;
            var op = _op_def_lib._apply_op_helper("ResourceGather", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Adds sparse updates to the variable referenced by <c>resource</c>.
        /// </summary>
        /// <param name="resource">
        ///    Should be from a <c>Variable</c> node.
        /// </param>
        /// <param name="indices">
        ///    A tensor of indices into the first dimension of <c>ref</c>.
        /// </param>
        /// <param name="updates">
        ///    A tensor of updated values to add to <c>ref</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceScatterAdd'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    This operation computes
        ///    
        ///    # Scalar indices
        ///    ref[indices, ...] += updates[...]
        ///    
        ///    # Vector indices (for each i)
        ///    ref[indices[i], ...] += updates[i, ...]
        ///    
        ///    # High rank indices (for each i, ..., j)
        ///    ref[indices[i, ..., j], ...] += updates[i, ..., j, ...]
        ///    
        ///    Duplicate entries are handled correctly: if multiple <c>indices</c> reference
        ///    the same location, their contributions add.
        ///    
        ///    Requires <c>updates.shape = indices.shape + ref.shape[1:]</c> or <c>updates.shape = []</c>.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src='https://www.tensorflow.org/images/ScatterAdd.png' alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Operation resource_scatter_add (Tensor resource, Tensor indices, Tensor updates, string name = "ResourceScatterAdd")
        {
            var dict = new Dictionary<string, object>();
            dict["resource"] = resource;
            dict["indices"] = indices;
            dict["updates"] = updates;
            var op = _op_def_lib._apply_op_helper("ResourceScatterAdd", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Divides sparse updates into the variable referenced by <c>resource</c>.
        /// </summary>
        /// <param name="resource">
        ///    Should be from a <c>Variable</c> node.
        /// </param>
        /// <param name="indices">
        ///    A tensor of indices into the first dimension of <c>ref</c>.
        /// </param>
        /// <param name="updates">
        ///    A tensor of updated values to add to <c>ref</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceScatterDiv'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    This operation computes
        ///    
        ///    # Scalar indices
        ///    ref[indices, ...] /= updates[...]
        ///    
        ///    # Vector indices (for each i)
        ///    ref[indices[i], ...] /= updates[i, ...]
        ///    
        ///    # High rank indices (for each i, ..., j)
        ///    ref[indices[i, ..., j], ...] /= updates[i, ..., j, ...]
        ///    
        ///    Duplicate entries are handled correctly: if multiple <c>indices</c> reference
        ///    the same location, their contributions multiply.
        ///    
        ///    Requires <c>updates.shape = indices.shape + ref.shape[1:]</c> or <c>updates.shape = []</c>.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src='https://www.tensorflow.org/images/ScatterAdd.png' alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Operation resource_scatter_div (Tensor resource, Tensor indices, Tensor updates, string name = "ResourceScatterDiv")
        {
            var dict = new Dictionary<string, object>();
            dict["resource"] = resource;
            dict["indices"] = indices;
            dict["updates"] = updates;
            var op = _op_def_lib._apply_op_helper("ResourceScatterDiv", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Reduces sparse updates into the variable referenced by <c>resource</c> using the <c>max</c> operation.
        /// </summary>
        /// <param name="resource">
        ///    Should be from a <c>Variable</c> node.
        /// </param>
        /// <param name="indices">
        ///    A tensor of indices into the first dimension of <c>ref</c>.
        /// </param>
        /// <param name="updates">
        ///    A tensor of updated values to add to <c>ref</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceScatterMax'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    This operation computes
        ///    
        ///    # Scalar indices
        ///    ref[indices, ...] = max(ref[indices, ...], updates[...])
        ///    
        ///    # Vector indices (for each i)
        ///    ref[indices[i], ...] = max(ref[indices[i], ...], updates[i, ...])
        ///    
        ///    # High rank indices (for each i, ..., j)
        ///    ref[indices[i, ..., j], ...] = max(ref[indices[i, ..., j], ...], updates[i, ..., j, ...])
        ///    
        ///    Duplicate entries are handled correctly: if multiple <c>indices</c> reference
        ///    the same location, their contributions are combined.
        ///    
        ///    Requires <c>updates.shape = indices.shape + ref.shape[1:]</c> or <c>updates.shape = []</c>.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src='https://www.tensorflow.org/images/ScatterAdd.png' alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Operation resource_scatter_max (Tensor resource, Tensor indices, Tensor updates, string name = "ResourceScatterMax")
        {
            var dict = new Dictionary<string, object>();
            dict["resource"] = resource;
            dict["indices"] = indices;
            dict["updates"] = updates;
            var op = _op_def_lib._apply_op_helper("ResourceScatterMax", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Reduces sparse updates into the variable referenced by <c>resource</c> using the <c>min</c> operation.
        /// </summary>
        /// <param name="resource">
        ///    Should be from a <c>Variable</c> node.
        /// </param>
        /// <param name="indices">
        ///    A tensor of indices into the first dimension of <c>ref</c>.
        /// </param>
        /// <param name="updates">
        ///    A tensor of updated values to add to <c>ref</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceScatterMin'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    This operation computes
        ///    
        ///    # Scalar indices
        ///    ref[indices, ...] = min(ref[indices, ...], updates[...])
        ///    
        ///    # Vector indices (for each i)
        ///    ref[indices[i], ...] = min(ref[indices[i], ...], updates[i, ...])
        ///    
        ///    # High rank indices (for each i, ..., j)
        ///    ref[indices[i, ..., j], ...] = min(ref[indices[i, ..., j], ...], updates[i, ..., j, ...])
        ///    
        ///    Duplicate entries are handled correctly: if multiple <c>indices</c> reference
        ///    the same location, their contributions are combined.
        ///    
        ///    Requires <c>updates.shape = indices.shape + ref.shape[1:]</c> or <c>updates.shape = []</c>.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src='https://www.tensorflow.org/images/ScatterAdd.png' alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Operation resource_scatter_min (Tensor resource, Tensor indices, Tensor updates, string name = "ResourceScatterMin")
        {
            var dict = new Dictionary<string, object>();
            dict["resource"] = resource;
            dict["indices"] = indices;
            dict["updates"] = updates;
            var op = _op_def_lib._apply_op_helper("ResourceScatterMin", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Multiplies sparse updates into the variable referenced by <c>resource</c>.
        /// </summary>
        /// <param name="resource">
        ///    Should be from a <c>Variable</c> node.
        /// </param>
        /// <param name="indices">
        ///    A tensor of indices into the first dimension of <c>ref</c>.
        /// </param>
        /// <param name="updates">
        ///    A tensor of updated values to add to <c>ref</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceScatterMul'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    This operation computes
        ///    
        ///    # Scalar indices
        ///    ref[indices, ...] *= updates[...]
        ///    
        ///    # Vector indices (for each i)
        ///    ref[indices[i], ...] *= updates[i, ...]
        ///    
        ///    # High rank indices (for each i, ..., j)
        ///    ref[indices[i, ..., j], ...] *= updates[i, ..., j, ...]
        ///    
        ///    Duplicate entries are handled correctly: if multiple <c>indices</c> reference
        ///    the same location, their contributions multiply.
        ///    
        ///    Requires <c>updates.shape = indices.shape + ref.shape[1:]</c> or <c>updates.shape = []</c>.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src='https://www.tensorflow.org/images/ScatterAdd.png' alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Operation resource_scatter_mul (Tensor resource, Tensor indices, Tensor updates, string name = "ResourceScatterMul")
        {
            var dict = new Dictionary<string, object>();
            dict["resource"] = resource;
            dict["indices"] = indices;
            dict["updates"] = updates;
            var op = _op_def_lib._apply_op_helper("ResourceScatterMul", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Adds sparse <c>updates</c> to individual values or slices within a given
        /// </summary>
        /// <param name="referecne">
        ///    A resource handle. Must be from a VarHandleOp.
        /// </param>
        /// <param name="indices">
        ///    A Tensor. Must be one of the following types: int32, int64.
        ///    A tensor of indices into ref.
        /// </param>
        /// <param name="updates">
        ///    A Tensor. Must have the same type as ref. A tensor of
        ///    values to add to ref.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceScatterNdAdd'.
        /// </param>
        /// <param name="use_locking">
        ///    An optional bool. Defaults to True. If True, the assignment will
        ///    be protected by a lock; otherwise the behavior is undefined,
        ///    but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    variable according to <c>indices</c>.
        ///    
        ///    <c>ref</c> is a <c>Tensor</c> with rank <c>P</c> and <c>indices</c> is a <c>Tensor</c> of rank <c>Q</c>.
        ///    
        ///    <c>indices</c> must be integer tensor, containing indices into <c>ref</c>.
        ///    It must be shape <c>[d_0, ..., d_{Q-2}, K]</c> where <c>0 &amp;lt; K &amp;lt;= P</c>.
        ///    
        ///    The innermost dimension of <c>indices</c> (with length <c>K</c>) corresponds to
        ///    indices into elements (if <c>K = P</c>) or slices (if <c>K &amp;lt; P</c>) along the <c>K</c>th
        ///    dimension of <c>ref</c>.
        ///    
        ///    <c>updates</c> is <c>Tensor</c> of rank <c>Q-1+P-K</c> with shape:
        ///    
        ///   <code>
        ///    [d_0, ..., d_{Q-2}, ref.shape[K], ..., ref.shape[P-1]].
        ///   </code>
        ///    
        ///    For example, say we want to update 4 scattered elements to a rank-1 tensor to
        ///    8 elements. In Python, that update would look like this:
        ///    
        ///   <code>
        ///    ref = tf.Variable([1, 2, 3, 4, 5, 6, 7, 8], use_resource=True)
        ///    indices = tf.constant([[4], [3], [1] ,[7]])
        ///    updates = tf.constant([9, 10, 11, 12])
        ///    update = tf.scatter_nd_add(ref, indices, updates)
        ///    with tf.Session() as sess:
        ///    print sess.run(update)
        ///   </code>
        ///    
        ///    The resulting update to ref would look like this:
        ///    
        ///    [1, 12, 3, 14, 14, 6, 7, 20]
        ///    
        ///    See <c>tf.scatter_nd</c> for more details about how to make updates to
        ///    slices.
        /// </remarks>
        public static Operation resource_scatter_nd_add (Tensor referecne, Tensor indices, Tensor updates, bool? use_locking = null, string name = "ResourceScatterNdAdd")
        {
            var dict = new Dictionary<string, object>();
            dict["ref"] = referecne;
            dict["indices"] = indices;
            dict["updates"] = updates;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceScatterNdAdd", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Applies sparse <c>updates</c> to individual values or slices within a given
        /// </summary>
        /// <param name="referecne">
        ///    A resource handle. Must be from a VarHandleOp.
        /// </param>
        /// <param name="indices">
        ///    A Tensor. Must be one of the following types: int32, int64.
        ///    A tensor of indices into ref.
        /// </param>
        /// <param name="updates">
        ///    A Tensor. Must have the same type as ref. A tensor of updated
        ///    values to add to ref.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceScatterNdUpdate'.
        /// </param>
        /// <param name="use_locking">
        ///    An optional bool. Defaults to True. If True, the assignment will
        ///    be protected by a lock; otherwise the behavior is undefined,
        ///    but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    variable according to <c>indices</c>.
        ///    
        ///    <c>ref</c> is a <c>Tensor</c> with rank <c>P</c> and <c>indices</c> is a <c>Tensor</c> of rank <c>Q</c>.
        ///    
        ///    <c>indices</c> must be integer tensor, containing indices into <c>ref</c>.
        ///    It must be shape <c>[d_0, ..., d_{Q-2}, K]</c> where <c>0 &amp;lt; K &amp;lt;= P</c>.
        ///    
        ///    The innermost dimension of <c>indices</c> (with length <c>K</c>) corresponds to
        ///    indices into elements (if <c>K = P</c>) or slices (if <c>K &amp;lt; P</c>) along the <c>K</c>th
        ///    dimension of <c>ref</c>.
        ///    
        ///    <c>updates</c> is <c>Tensor</c> of rank <c>Q-1+P-K</c> with shape:
        ///    
        ///   <code>
        ///    [d_0, ..., d_{Q-2}, ref.shape[K], ..., ref.shape[P-1]].
        ///   </code>
        ///    
        ///    For example, say we want to update 4 scattered elements to a rank-1 tensor to
        ///    8 elements. In Python, that update would look like this:
        ///    
        ///   <code>
        ///    ref = tf.Variable([1, 2, 3, 4, 5, 6, 7, 8])
        ///    indices = tf.constant([[4], [3], [1] ,[7]])
        ///    updates = tf.constant([9, 10, 11, 12])
        ///    update = tf.scatter_nd_update(ref, indices, updates)
        ///    with tf.Session() as sess:
        ///    print sess.run(update)
        ///   </code>
        ///    
        ///    The resulting update to ref would look like this:
        ///    
        ///    [1, 11, 3, 10, 9, 6, 7, 12]
        ///    
        ///    See <c>tf.scatter_nd</c> for more details about how to make updates to
        ///    slices.
        /// </remarks>
        public static Operation resource_scatter_nd_update (Tensor referecne, Tensor indices, Tensor updates, bool? use_locking = null, string name = "ResourceScatterNdUpdate")
        {
            var dict = new Dictionary<string, object>();
            dict["ref"] = referecne;
            dict["indices"] = indices;
            dict["updates"] = updates;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceScatterNdUpdate", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Subtracts sparse updates from the variable referenced by <c>resource</c>.
        /// </summary>
        /// <param name="resource">
        ///    Should be from a <c>Variable</c> node.
        /// </param>
        /// <param name="indices">
        ///    A tensor of indices into the first dimension of <c>ref</c>.
        /// </param>
        /// <param name="updates">
        ///    A tensor of updated values to add to <c>ref</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceScatterSub'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    This operation computes
        ///    
        ///    # Scalar indices
        ///    ref[indices, ...] -= updates[...]
        ///    
        ///    # Vector indices (for each i)
        ///    ref[indices[i], ...] -= updates[i, ...]
        ///    
        ///    # High rank indices (for each i, ..., j)
        ///    ref[indices[i, ..., j], ...] -= updates[i, ..., j, ...]
        ///    
        ///    Duplicate entries are handled correctly: if multiple <c>indices</c> reference
        ///    the same location, their contributions add.
        ///    
        ///    Requires <c>updates.shape = indices.shape + ref.shape[1:]</c> or <c>updates.shape = []</c>.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src='https://www.tensorflow.org/images/ScatterAdd.png' alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Operation resource_scatter_sub (Tensor resource, Tensor indices, Tensor updates, string name = "ResourceScatterSub")
        {
            var dict = new Dictionary<string, object>();
            dict["resource"] = resource;
            dict["indices"] = indices;
            dict["updates"] = updates;
            var op = _op_def_lib._apply_op_helper("ResourceScatterSub", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Assigns sparse updates to the variable referenced by <c>resource</c>.
        /// </summary>
        /// <param name="resource">
        ///    Should be from a <c>Variable</c> node.
        /// </param>
        /// <param name="indices">
        ///    A tensor of indices into the first dimension of <c>ref</c>.
        /// </param>
        /// <param name="updates">
        ///    A tensor of updated values to add to <c>ref</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceScatterUpdate'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    This operation computes
        ///    
        ///    # Scalar indices
        ///    ref[indices, ...] = updates[...]
        ///    
        ///    # Vector indices (for each i)
        ///    ref[indices[i], ...] = updates[i, ...]
        ///    
        ///    # High rank indices (for each i, ..., j)
        ///    ref[indices[i, ..., j], ...] = updates[i, ..., j, ...]
        /// </remarks>
        public static Operation resource_scatter_update (Tensor resource, Tensor indices, Tensor updates, string name = "ResourceScatterUpdate")
        {
            var dict = new Dictionary<string, object>();
            dict["resource"] = resource;
            dict["indices"] = indices;
            dict["updates"] = updates;
            var op = _op_def_lib._apply_op_helper("ResourceScatterUpdate", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    var: Should be from a Variable().
        /// </summary>
        /// <param name="var">
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum_update">
        ///    : Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Learning rate. Must be a scalar.
        /// </param>
        /// <param name="rho">
        ///    Decay factor. Must be a scalar.
        /// </param>
        /// <param name="epsilon">
        ///    Constant factor. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="indices">
        ///    A vector of indices into the first dimension of var and accum.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceSparseApplyAdadelta'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, updating of the var and accum tensors will be protected by
        ///    a lock; otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation resource_sparse_apply_adadelta (Tensor var, Tensor accum, Tensor accum_update, Tensor lr, Tensor rho, Tensor epsilon, Tensor grad, Tensor indices, bool? use_locking = null, string name = "ResourceSparseApplyAdadelta")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["accum_update"] = accum_update;
            dict["lr"] = lr;
            dict["rho"] = rho;
            dict["epsilon"] = epsilon;
            dict["grad"] = grad;
            dict["indices"] = indices;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceSparseApplyAdadelta", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update relevant entries in '*var' and '*accum' according to the adagrad scheme.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Learning rate. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="indices">
        ///    A vector of indices into the first dimension of var and accum.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceSparseApplyAdagrad'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var and accum tensors will be protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <param name="update_slots">
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    That is for rows we have grad for, we update var and accum as follows:
        ///    accum += grad * grad
        ///    var -= lr * grad * (1 / sqrt(accum))
        /// </remarks>
        public static Operation resource_sparse_apply_adagrad (Tensor var, Tensor accum, Tensor lr, Tensor grad, Tensor indices, bool? use_locking = null, bool? update_slots = null, string name = "ResourceSparseApplyAdagrad")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["lr"] = lr;
            dict["grad"] = grad;
            dict["indices"] = indices;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            if (update_slots.HasValue)
                dict["update_slots"] = update_slots.Value;
            var op = _op_def_lib._apply_op_helper("ResourceSparseApplyAdagrad", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update entries in '*var' and '*accum' according to the proximal adagrad scheme.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="gradient_accumulator">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="gradient_squared_accumulator">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="indices">
        ///    A vector of indices into the first dimension of var and accum.
        /// </param>
        /// <param name="lr">
        ///    Learning rate. Must be a scalar.
        /// </param>
        /// <param name="l1">
        ///    L1 regularization. Must be a scalar.
        /// </param>
        /// <param name="l2">
        ///    L2 regularization. Must be a scalar.
        /// </param>
        /// <param name="global_step">
        ///    Training step number. Must be a scalar.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceSparseApplyAdagradDA'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, updating of the var and accum tensors will be protected by
        ///    a lock; otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation resource_sparse_apply_adagrad_d_a (Tensor var, Tensor gradient_accumulator, Tensor gradient_squared_accumulator, Tensor grad, Tensor indices, Tensor lr, Tensor l1, Tensor l2, Tensor global_step, bool? use_locking = null, string name = "ResourceSparseApplyAdagradDA")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["gradient_accumulator"] = gradient_accumulator;
            dict["gradient_squared_accumulator"] = gradient_squared_accumulator;
            dict["grad"] = grad;
            dict["indices"] = indices;
            dict["lr"] = lr;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["global_step"] = global_step;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceSparseApplyAdagradDA", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update '*var' according to the centered RMSProp algorithm.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="mg">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="ms">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="mom">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="rho">
        ///    Decay rate. Must be a scalar.
        /// </param>
        /// <param name="momentum">
        /// </param>
        /// <param name="epsilon">
        ///    Ridge term. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="indices">
        ///    A vector of indices into the first dimension of var, ms and mom.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceSparseApplyCenteredRMSProp'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var, mg, ms, and mom tensors is
        ///    protected by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    The centered RMSProp algorithm uses an estimate of the centered second moment
        ///    (i.e., the variance) for normalization, as opposed to regular RMSProp, which
        ///    uses the (uncentered) second moment. This often helps with training, but is
        ///    slightly more expensive in terms of computation and memory.
        ///    
        ///    Note that in dense implementation of this algorithm, mg, ms, and mom will
        ///    update even if the grad is zero, but in this sparse implementation, mg, ms,
        ///    and mom will not update in iterations during which the grad is zero.
        ///    
        ///    mean_square = decay * mean_square + (1-decay) * gradient ** 2
        ///    mean_grad = decay * mean_grad + (1-decay) * gradient
        ///    Delta = learning_rate * gradient / sqrt(mean_square + epsilon - mean_grad ** 2)
        ///    
        ///    ms &amp;lt;- rho * ms_{t-1} + (1-rho) * grad * grad
        ///    mom &amp;lt;- momentum * mom_{t-1} + lr * grad / sqrt(ms + epsilon)
        ///    var &amp;lt;- var - mom
        /// </remarks>
        public static Operation resource_sparse_apply_centered_r_m_s_prop (Tensor var, Tensor mg, Tensor ms, Tensor mom, Tensor lr, Tensor rho, Tensor momentum, Tensor epsilon, Tensor grad, Tensor indices, bool? use_locking = null, string name = "ResourceSparseApplyCenteredRMSProp")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["mg"] = mg;
            dict["ms"] = ms;
            dict["mom"] = mom;
            dict["lr"] = lr;
            dict["rho"] = rho;
            dict["momentum"] = momentum;
            dict["epsilon"] = epsilon;
            dict["grad"] = grad;
            dict["indices"] = indices;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceSparseApplyCenteredRMSProp", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update relevant entries in '*var' according to the Ftrl-proximal scheme.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="linear">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="indices">
        ///    A vector of indices into the first dimension of var and accum.
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="l1">
        ///    L1 regularization. Must be a scalar.
        /// </param>
        /// <param name="l2">
        ///    L2 regularization. Must be a scalar.
        /// </param>
        /// <param name="lr_power">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceSparseApplyFtrl'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var and accum tensors will be protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    That is for rows we have grad for, we update var, accum and linear as follows:
        ///    accum_new = accum + grad * grad
        ///    linear += grad + (accum_new^(-lr_power) - accum^(-lr_power)) / lr * var
        ///    quadratic = 1.0 / (accum_new^(lr_power) * lr) + 2 * l2
        ///    var = (sign(linear) * l1 - linear) / quadratic if |linear| &amp;gt; l1 else 0.0
        ///    accum = accum_new
        /// </remarks>
        public static Operation resource_sparse_apply_ftrl (Tensor var, Tensor accum, Tensor linear, Tensor grad, Tensor indices, Tensor lr, Tensor l1, Tensor l2, Tensor lr_power, bool? use_locking = null, string name = "ResourceSparseApplyFtrl")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["linear"] = linear;
            dict["grad"] = grad;
            dict["indices"] = indices;
            dict["lr"] = lr;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["lr_power"] = lr_power;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceSparseApplyFtrl", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update relevant entries in '*var' according to the Ftrl-proximal scheme.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="linear">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="indices">
        ///    A vector of indices into the first dimension of var and accum.
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="l1">
        ///    L1 regularization. Must be a scalar.
        /// </param>
        /// <param name="l2">
        ///    L2 shrinkage regulariation. Must be a scalar.
        /// </param>
        /// <param name="l2_shrinkage">
        /// </param>
        /// <param name="lr_power">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceSparseApplyFtrlV2'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var and accum tensors will be protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    That is for rows we have grad for, we update var, accum and linear as follows:
        ///    grad_with_shrinkage = grad + 2 * l2_shrinkage * var
        ///    accum_new = accum + grad_with_shrinkage * grad_with_shrinkage
        ///    linear += grad_with_shrinkage +
        ///    (accum_new^(-lr_power) - accum^(-lr_power)) / lr * var
        ///    quadratic = 1.0 / (accum_new^(lr_power) * lr) + 2 * l2
        ///    var = (sign(linear) * l1 - linear) / quadratic if |linear| &amp;gt; l1 else 0.0
        ///    accum = accum_new
        /// </remarks>
        public static Operation resource_sparse_apply_ftrl_v2 (Tensor var, Tensor accum, Tensor linear, Tensor grad, Tensor indices, Tensor lr, Tensor l1, Tensor l2, Tensor l2_shrinkage, Tensor lr_power, bool? use_locking = null, string name = "ResourceSparseApplyFtrlV2")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["linear"] = linear;
            dict["grad"] = grad;
            dict["indices"] = indices;
            dict["lr"] = lr;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["l2_shrinkage"] = l2_shrinkage;
            dict["lr_power"] = lr_power;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceSparseApplyFtrlV2", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update relevant entries in '*var' and '*accum' according to the momentum scheme.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Learning rate. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="indices">
        ///    A vector of indices into the first dimension of var and accum.
        /// </param>
        /// <param name="momentum">
        ///    Momentum. Must be a scalar.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceSparseApplyMomentum'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var and accum tensors will be protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <param name="use_nesterov">
        ///    If <c>True</c>, the tensor passed to compute grad will be
        ///    var - lr * momentum * accum, so in the end, the var you get is actually
        ///    var - lr * momentum * accum.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    Set use_nesterov = True if you want to use Nesterov momentum.
        ///    
        ///    That is for rows we have grad for, we update var and accum as follows:
        ///    
        ///    accum = accum * momentum + grad
        ///    var -= lr * accum
        /// </remarks>
        public static Operation resource_sparse_apply_momentum (Tensor var, Tensor accum, Tensor lr, Tensor grad, Tensor indices, Tensor momentum, bool? use_locking = null, bool? use_nesterov = null, string name = "ResourceSparseApplyMomentum")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["lr"] = lr;
            dict["grad"] = grad;
            dict["indices"] = indices;
            dict["momentum"] = momentum;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            if (use_nesterov.HasValue)
                dict["use_nesterov"] = use_nesterov.Value;
            var op = _op_def_lib._apply_op_helper("ResourceSparseApplyMomentum", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Sparse update entries in '*var' and '*accum' according to FOBOS algorithm.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Learning rate. Must be a scalar.
        /// </param>
        /// <param name="l1">
        ///    L1 regularization. Must be a scalar.
        /// </param>
        /// <param name="l2">
        ///    L2 regularization. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="indices">
        ///    A vector of indices into the first dimension of var and accum.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceSparseApplyProximalAdagrad'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, updating of the var and accum tensors will be protected by
        ///    a lock; otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    That is for rows we have grad for, we update var and accum as follows:
        ///    accum += grad * grad
        ///    prox_v = var
        ///    prox_v -= lr * grad * (1 / sqrt(accum))
        ///    var = sign(prox_v)/(1+lr*l2) * max{|prox_v|-lr*l1,0}
        /// </remarks>
        public static Operation resource_sparse_apply_proximal_adagrad (Tensor var, Tensor accum, Tensor lr, Tensor l1, Tensor l2, Tensor grad, Tensor indices, bool? use_locking = null, string name = "ResourceSparseApplyProximalAdagrad")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["lr"] = lr;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["grad"] = grad;
            dict["indices"] = indices;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceSparseApplyProximalAdagrad", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Sparse update '*var' as FOBOS algorithm with fixed learning rate.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="alpha">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="l1">
        ///    L1 regularization. Must be a scalar.
        /// </param>
        /// <param name="l2">
        ///    L2 regularization. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="indices">
        ///    A vector of indices into the first dimension of var and accum.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceSparseApplyProximalGradientDescent'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, the subtraction will be protected by a lock;
        ///    otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    That is for rows we have grad for, we update var as follows:
        ///    prox_v = var - alpha * grad
        ///    var = sign(prox_v)/(1+alpha*l2) * max{|prox_v|-alpha*l1,0}
        /// </remarks>
        public static Operation resource_sparse_apply_proximal_gradient_descent (Tensor var, Tensor alpha, Tensor l1, Tensor l2, Tensor grad, Tensor indices, bool? use_locking = null, string name = "ResourceSparseApplyProximalGradientDescent")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["alpha"] = alpha;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["grad"] = grad;
            dict["indices"] = indices;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceSparseApplyProximalGradientDescent", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Update '*var' according to the RMSProp algorithm.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="ms">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="mom">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="rho">
        ///    Decay rate. Must be a scalar.
        /// </param>
        /// <param name="momentum">
        /// </param>
        /// <param name="epsilon">
        ///    Ridge term. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="indices">
        ///    A vector of indices into the first dimension of var, ms and mom.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceSparseApplyRMSProp'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var, ms, and mom tensors is protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    Note that in dense implementation of this algorithm, ms and mom will
        ///    update even if the grad is zero, but in this sparse implementation, ms
        ///    and mom will not update in iterations during which the grad is zero.
        ///    
        ///    mean_square = decay * mean_square + (1-decay) * gradient ** 2
        ///    Delta = learning_rate * gradient / sqrt(mean_square + epsilon)
        ///    
        ///    ms &amp;lt;- rho * ms_{t-1} + (1-rho) * grad * grad
        ///    mom &amp;lt;- momentum * mom_{t-1} + lr * grad / sqrt(ms + epsilon)
        ///    var &amp;lt;- var - mom
        /// </remarks>
        public static Operation resource_sparse_apply_r_m_s_prop (Tensor var, Tensor ms, Tensor mom, Tensor lr, Tensor rho, Tensor momentum, Tensor epsilon, Tensor grad, Tensor indices, bool? use_locking = null, string name = "ResourceSparseApplyRMSProp")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["ms"] = ms;
            dict["mom"] = mom;
            dict["lr"] = lr;
            dict["rho"] = rho;
            dict["momentum"] = momentum;
            dict["epsilon"] = epsilon;
            dict["grad"] = grad;
            dict["indices"] = indices;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ResourceSparseApplyRMSProp", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Assign <c>value</c> to the sliced l-value reference of <c>ref</c>.
        /// </summary>
        /// <param name="referecne">
        /// </param>
        /// <param name="begin">
        /// </param>
        /// <param name="end">
        /// </param>
        /// <param name="strides">
        /// </param>
        /// <param name="value">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ResourceStridedSliceAssign'.
        /// </param>
        /// <param name="begin_mask">
        /// </param>
        /// <param name="end_mask">
        /// </param>
        /// <param name="ellipsis_mask">
        /// </param>
        /// <param name="new_axis_mask">
        /// </param>
        /// <param name="shrink_axis_mask">
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    The values of <c>value</c> are assigned to the positions in the variable
        ///    <c>ref</c> that are selected by the slice parameters. The slice parameters
        ///    <c>begin, </c>end<c>, </c>strides<c>, etc. work exactly as in </c>StridedSlice<c>.
        ///    
        ///    NOTE this op currently does not support broadcasting and so </c>value<c>'s
        ///    shape must be exactly the shape produced by the slice of </c>ref<c>.
        /// </remarks>
        public static Operation resource_strided_slice_assign (Tensor referecne, Tensor begin, Tensor end, Tensor strides, Tensor value, int? begin_mask = null, int? end_mask = null, int? ellipsis_mask = null, int? new_axis_mask = null, int? shrink_axis_mask = null, string name = "ResourceStridedSliceAssign")
        {
            var dict = new Dictionary<string, object>();
            dict["ref"] = referecne;
            dict["begin"] = begin;
            dict["end"] = end;
            dict["strides"] = strides;
            dict["value"] = value;
            if (begin_mask.HasValue)
                dict["begin_mask"] = begin_mask.Value;
            if (end_mask.HasValue)
                dict["end_mask"] = end_mask.Value;
            if (ellipsis_mask.HasValue)
                dict["ellipsis_mask"] = ellipsis_mask.Value;
            if (new_axis_mask.HasValue)
                dict["new_axis_mask"] = new_axis_mask.Value;
            if (shrink_axis_mask.HasValue)
                dict["shrink_axis_mask"] = shrink_axis_mask.Value;
            var op = _op_def_lib._apply_op_helper("ResourceStridedSliceAssign", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Restores a tensor from checkpoint files.
        /// </summary>
        /// <param name="file_pattern">
        ///    Must have a single element. The pattern of the files from
        ///    which we read the tensor.
        /// </param>
        /// <param name="tensor_name">
        ///    Must have a single element. The name of the tensor to be
        ///    restored.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Restore'.
        /// </param>
        /// <param name="dt">
        ///    Optional argument
        ///    The type of the tensor to be restored.
        /// </param>
        /// <param name="preferred_shard">
        ///    Index of file to open first if multiple files match
        ///    <c>file_pattern</c>.
        /// </param>
        /// <returns>
        ///    The restored tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Reads a tensor stored in one or several files. If there are several files (for
        ///    instance because a tensor was saved as slices), <c>file_pattern</c> may contain
        ///    wildcard symbols (<c>*</c> and <c>?</c>) in the filename portion only, not in the
        ///    directory portion.
        ///    
        ///    If a <c>file_pattern</c> matches several files, <c>preferred_shard</c> can be used to hint
        ///    in which file the requested tensor is likely to be found. This op will first
        ///    open the file at index <c>preferred_shard</c> in the list of matching files and try
        ///    to restore tensors from that file.  Only if some tensors or tensor slices are
        ///    not found in that first file, then the Op opens all the files. Setting
        ///    <c>preferred_shard</c> to match the value passed as the <c>shard</c> input
        ///    of a matching <c>Save</c> Op may speed up Restore.  This attribute only affects
        ///    performance, not correctness.  The default value -1 means files are processed in
        ///    order.
        ///    
        ///    See also <c>RestoreSlice</c>.
        /// </remarks>
        public static Tensor restore (Tensor file_pattern, Tensor tensor_name, TF_DataType dt, int? preferred_shard = null, string name = "Restore")
        {
            var dict = new Dictionary<string, object>();
            dict["file_pattern"] = file_pattern;
            dict["tensor_name"] = tensor_name;
            dict["dt"] = dt;
            if (preferred_shard.HasValue)
                dict["preferred_shard"] = preferred_shard.Value;
            var op = _op_def_lib._apply_op_helper("Restore", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Restores a tensor from checkpoint files.
        /// </summary>
        /// <param name="file_pattern">
        ///    Must have a single element. The pattern of the files from
        ///    which we read the tensor.
        /// </param>
        /// <param name="tensor_name">
        ///    Must have a single element. The name of the tensor to be
        ///    restored.
        /// </param>
        /// <param name="shape_and_slice">
        ///    Scalar. The shapes and slice specifications to use when
        ///    restoring a tensors.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RestoreSlice'.
        /// </param>
        /// <param name="dt">
        ///    Optional argument
        ///    The type of the tensor to be restored.
        /// </param>
        /// <param name="preferred_shard">
        ///    Index of file to open first if multiple files match
        ///    <c>file_pattern</c>. See the documentation for <c>Restore</c>.
        /// </param>
        /// <returns>
        ///    The restored tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This is like <c>Restore</c> except that restored tensor can be listed as filling
        ///    only a slice of a larger tensor.  <c>shape_and_slice</c> specifies the shape of the
        ///    larger tensor and the slice that the restored tensor covers.
        ///    
        ///    The <c>shape_and_slice</c> input has the same format as the
        ///    elements of the <c>shapes_and_slices</c> input of the <c>SaveSlices</c> op.
        /// </remarks>
        public static Tensor restore_slice (Tensor file_pattern, Tensor tensor_name, Tensor shape_and_slice, TF_DataType dt, int? preferred_shard = null, string name = "RestoreSlice")
        {
            var dict = new Dictionary<string, object>();
            dict["file_pattern"] = file_pattern;
            dict["tensor_name"] = tensor_name;
            dict["shape_and_slice"] = shape_and_slice;
            dict["dt"] = dt;
            if (preferred_shard.HasValue)
                dict["preferred_shard"] = preferred_shard.Value;
            var op = _op_def_lib._apply_op_helper("RestoreSlice", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Restores tensors from a V2 checkpoint.
        /// </summary>
        /// <param name="prefix">
        ///    Must have a single element.  The prefix of a V2 checkpoint.
        /// </param>
        /// <param name="tensor_names">
        ///    shape {N}.  The names of the tensors to be restored.
        /// </param>
        /// <param name="shape_and_slices">
        ///    shape {N}.  The slice specs of the tensors to be restored.
        ///    Empty strings indicate that they are non-partitioned tensors.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RestoreV2'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        ///    shape {N}.  The list of expected dtype for the tensors.  Must match
        ///    those stored in the checkpoint.
        /// </param>
        /// <returns>
        ///    shape {N}.  The restored tensors, whose shapes are read from the
        ///    checkpoint directly.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    For backward compatibility with the V1 format, this Op currently allows
        ///    restoring from a V1 checkpoint as well:
        ///    - This Op first attempts to find the V2 index file pointed to by "prefix", and
        ///    if found proceed to read it as a V2 checkpoint;
        ///    - Otherwise the V1 read path is invoked.
        ///    Relying on this behavior is not recommended, as the ability to fall back to read
        ///    V1 might be deprecated and eventually removed.
        ///    
        ///    By default, restores the named tensors in full.  If the caller wishes to restore
        ///    specific slices of stored tensors, "shape_and_slices" should be non-empty
        ///    strings and correspondingly well-formed.
        ///    
        ///    Callers must ensure all the named tensors are indeed stored in the checkpoint.
        /// </remarks>
        public static Tensor[] restore_v2 (Tensor prefix, Tensor tensor_names, Tensor shape_and_slices, TF_DataType[] dtypes, string name = "RestoreV2")
        {
            var dict = new Dictionary<string, object>();
            dict["prefix"] = prefix;
            dict["tensor_names"] = tensor_names;
            dict["shape_and_slices"] = shape_and_slices;
            dict["dtypes"] = dtypes;
            var op = _op_def_lib._apply_op_helper("RestoreV2", name: name, keywords: dict);
            int _idx = 0;
            var tensors = Enumerable.Range(0, op.OutputListLength("tensors")).Select(_ => op.outputs[_idx++]).ToArray();
            return (tensors);
        }

        /// <summary>
        ///    Reverses specific dimensions of a tensor.
        /// </summary>
        /// <param name="tensor">
        ///    Up to 8-D.
        /// </param>
        /// <param name="dims">
        ///    1-D. The dimensions to reverse.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Reverse'.
        /// </param>
        /// <returns>
        ///    The same shape as <c>tensor</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given a <c>tensor</c>, and a <c>bool</c> tensor <c>dims</c> representing the dimensions
        ///    of <c>tensor</c>, this operation reverses each dimension i of <c>tensor</c> where
        ///    <c>dims[i]</c> is <c>True</c>.
        ///    
        ///    <c>tensor</c> can have up to 8 dimensions. The number of dimensions
        ///    of <c>tensor</c> must equal the number of elements in <c>dims</c>. In other words:
        ///    
        ///    <c>rank(tensor) = size(dims)</c>
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # tensor 't' is [[[[ 0,  1,  2,  3],
        ///    #                  [ 4,  5,  6,  7],
        ///    #                  [ 8,  9, 10, 11]],
        ///    #                 [[12, 13, 14, 15],
        ///    #                  [16, 17, 18, 19],
        ///    #                  [20, 21, 22, 23]]]]
        ///    # tensor 't' shape is [1, 2, 3, 4]
        ///    
        ///    # 'dims' is [False, False, False, True]
        ///    reverse(t, dims) ==&amp;gt; [[[[ 3,  2,  1,  0],
        ///    [ 7,  6,  5,  4],
        ///    [ 11, 10, 9, 8]],
        ///    [[15, 14, 13, 12],
        ///    [19, 18, 17, 16],
        ///    [23, 22, 21, 20]]]]
        ///    
        ///    # 'dims' is [False, True, False, False]
        ///    reverse(t, dims) ==&amp;gt; [[[[12, 13, 14, 15],
        ///    [16, 17, 18, 19],
        ///    [20, 21, 22, 23]
        ///    [[ 0,  1,  2,  3],
        ///    [ 4,  5,  6,  7],
        ///    [ 8,  9, 10, 11]]]]
        ///    
        ///    # 'dims' is [False, False, True, False]
        ///    reverse(t, dims) ==&amp;gt; [[[[8, 9, 10, 11],
        ///    [4, 5, 6, 7],
        ///    [0, 1, 2, 3]]
        ///    [[20, 21, 22, 23],
        ///    [16, 17, 18, 19],
        ///    [12, 13, 14, 15]]]]
        ///   </code>
        /// </remarks>
        public static Tensor reverse (Tensor tensor, Tensor dims, string name = "Reverse")
        {
            var dict = new Dictionary<string, object>();
            dict["tensor"] = tensor;
            dict["dims"] = dims;
            var op = _op_def_lib._apply_op_helper("Reverse", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Reverses variable length slices.
        /// </summary>
        /// <param name="input">
        ///    The input to reverse.
        /// </param>
        /// <param name="seq_lengths">
        ///    1-D with length <c>input.dims(batch_dim)</c> and
        ///    <c>max(seq_lengths) &amp;lt;= input.dims(seq_dim)</c>
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReverseSequence'.
        /// </param>
        /// <param name="seq_dim">
        ///    Optional argument
        ///    The dimension which is partially reversed.
        /// </param>
        /// <param name="batch_dim">
        ///    The dimension along which reversal is performed.
        /// </param>
        /// <returns>
        ///    The partially reversed input. It has the same shape as <c>input</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op first slices <c>input</c> along the dimension <c>batch_dim</c>, and for each
        ///    slice <c>i</c>, reverses the first <c>seq_lengths[i]</c> elements along
        ///    the dimension <c>seq_dim</c>.
        ///    
        ///    The elements of <c>seq_lengths</c> must obey <c>seq_lengths[i] &amp;lt;= input.dims[seq_dim]</c>,
        ///    and <c>seq_lengths</c> must be a vector of length <c>input.dims[batch_dim]</c>.
        ///    
        ///    The output slice <c>i</c> along dimension <c>batch_dim</c> is then given by input
        ///    slice <c>i</c>, with the first <c>seq_lengths[i]</c> slices along dimension
        ///    <c>seq_dim</c> reversed.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # Given this:
        ///    batch_dim = 0
        ///    seq_dim = 1
        ///    input.dims = (4, 8, ...)
        ///    seq_lengths = [7, 2, 3, 5]
        ///    
        ///    # then slices of input are reversed on seq_dim, but only up to seq_lengths:
        ///    output[0, 0:7, :, ...] = input[0, 7:0:-1, :, ...]
        ///    output[1, 0:2, :, ...] = input[1, 2:0:-1, :, ...]
        ///    output[2, 0:3, :, ...] = input[2, 3:0:-1, :, ...]
        ///    output[3, 0:5, :, ...] = input[3, 5:0:-1, :, ...]
        ///    
        ///    # while entries past seq_lens are copied through:
        ///    output[0, 7:, :, ...] = input[0, 7:, :, ...]
        ///    output[1, 2:, :, ...] = input[1, 2:, :, ...]
        ///    output[2, 3:, :, ...] = input[2, 3:, :, ...]
        ///    output[3, 2:, :, ...] = input[3, 2:, :, ...]
        ///   </code>
        ///    
        ///    In contrast, if:
        ///    
        ///   <code>
        ///    # Given this:
        ///    batch_dim = 2
        ///    seq_dim = 0
        ///    input.dims = (8, ?, 4, ...)
        ///    seq_lengths = [7, 2, 3, 5]
        ///    
        ///    # then slices of input are reversed on seq_dim, but only up to seq_lengths:
        ///    output[0:7, :, 0, :, ...] = input[7:0:-1, :, 0, :, ...]
        ///    output[0:2, :, 1, :, ...] = input[2:0:-1, :, 1, :, ...]
        ///    output[0:3, :, 2, :, ...] = input[3:0:-1, :, 2, :, ...]
        ///    output[0:5, :, 3, :, ...] = input[5:0:-1, :, 3, :, ...]
        ///    
        ///    # while entries past seq_lens are copied through:
        ///    output[7:, :, 0, :, ...] = input[7:, :, 0, :, ...]
        ///    output[2:, :, 1, :, ...] = input[2:, :, 1, :, ...]
        ///    output[3:, :, 2, :, ...] = input[3:, :, 2, :, ...]
        ///    output[2:, :, 3, :, ...] = input[2:, :, 3, :, ...]
        ///   </code>
        /// </remarks>
        public static Tensor reverse_sequence (Tensor input, Tensor seq_lengths, int seq_dim, int? batch_dim = null, string name = "ReverseSequence")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["seq_lengths"] = seq_lengths;
            dict["seq_dim"] = seq_dim;
            if (batch_dim.HasValue)
                dict["batch_dim"] = batch_dim.Value;
            var op = _op_def_lib._apply_op_helper("ReverseSequence", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Reverses specific dimensions of a tensor.
        /// </summary>
        /// <param name="tensor">
        ///    Up to 8-D.
        /// </param>
        /// <param name="axis">
        ///    1-D. The indices of the dimensions to reverse. Must be in the range
        ///    <c>[-rank(tensor), rank(tensor))</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ReverseV2'.
        /// </param>
        /// <returns>
        ///    The same shape as <c>tensor</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    NOTE <c>tf.reverse</c> has now changed behavior in preparation for 1.0.
        ///    <c>tf.reverse_v2</c> is currently an alias that will be deprecated before TF 1.0.
        ///    
        ///    Given a <c>tensor</c>, and a <c>int32</c> tensor <c>axis</c> representing the set of
        ///    dimensions of <c>tensor</c> to reverse. This operation reverses each dimension
        ///    <c>i</c> for which there exists <c>j</c> s.t. <c>axis[j] == i</c>.
        ///    
        ///    <c>tensor</c> can have up to 8 dimensions. The number of dimensions specified
        ///    in <c>axis</c> may be 0 or more entries. If an index is specified more than
        ///    once, a InvalidArgument error is raised.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # tensor 't' is [[[[ 0,  1,  2,  3],
        ///    #                  [ 4,  5,  6,  7],
        ///    #                  [ 8,  9, 10, 11]],
        ///    #                 [[12, 13, 14, 15],
        ///    #                  [16, 17, 18, 19],
        ///    #                  [20, 21, 22, 23]]]]
        ///    # tensor 't' shape is [1, 2, 3, 4]
        ///    
        ///    # 'dims' is [3] or 'dims' is [-1]
        ///    reverse(t, dims) ==&amp;gt; [[[[ 3,  2,  1,  0],
        ///    [ 7,  6,  5,  4],
        ///    [ 11, 10, 9, 8]],
        ///    [[15, 14, 13, 12],
        ///    [19, 18, 17, 16],
        ///    [23, 22, 21, 20]]]]
        ///    
        ///    # 'dims' is '[1]' (or 'dims' is '[-3]')
        ///    reverse(t, dims) ==&amp;gt; [[[[12, 13, 14, 15],
        ///    [16, 17, 18, 19],
        ///    [20, 21, 22, 23]
        ///    [[ 0,  1,  2,  3],
        ///    [ 4,  5,  6,  7],
        ///    [ 8,  9, 10, 11]]]]
        ///    
        ///    # 'dims' is '[2]' (or 'dims' is '[-2]')
        ///    reverse(t, dims) ==&amp;gt; [[[[8, 9, 10, 11],
        ///    [4, 5, 6, 7],
        ///    [0, 1, 2, 3]]
        ///    [[20, 21, 22, 23],
        ///    [16, 17, 18, 19],
        ///    [12, 13, 14, 15]]]]
        ///   </code>
        /// </remarks>
        public static Tensor reverse_v2 (Tensor tensor, Tensor axis, string name = "ReverseV2")
        {
            var dict = new Dictionary<string, object>();
            dict["tensor"] = tensor;
            dict["axis"] = axis;
            var op = _op_def_lib._apply_op_helper("ReverseV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Elementwise computes the bitwise right-shift of <c>x</c> and <c>y</c>.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RightShift'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Performs a logical shift for unsigned integer types, and an arithmetic shift
        ///    for signed integer types.
        ///    
        ///    If <c>y</c> is negative, or greater than or equal to than the width of <c>x</c> in bits
        ///    the result is implementation defined.
        /// </remarks>
        public static Tensor right_shift (Tensor x, Tensor y, string name = "RightShift")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("RightShift", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns element-wise integer closest to x.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Rint'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    If the result is midway between two representable values,
        ///    the even representable is chosen.
        ///    For example:
        ///    
        ///   <code>
        ///    rint(-1.5) ==&amp;gt; -2.0
        ///    rint(0.5000001) ==&amp;gt; 1.0
        ///    rint([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]) ==&amp;gt; [-2., -2., -0., 0., 2., 2., 2.]
        ///   </code>
        /// </remarks>
        public static Tensor rint (Tensor x, string name = "Rint")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Rint", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Rolls the elements of a tensor along an axis.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="shift">
        ///    Dimension must be 0-D or 1-D. <c>shift[i]</c> specifies the number of places by which
        ///    elements are shifted positively (towards larger indices) along the dimension
        ///    specified by <c>axis[i]</c>. Negative shifts will roll the elements in the opposite
        ///    direction.
        /// </param>
        /// <param name="axis">
        ///    Dimension must be 0-D or 1-D. <c>axis[i]</c> specifies the dimension that the shift
        ///    <c>shift[i]</c> should occur. If the same axis is referenced more than once, the
        ///    total shift for that axis will be the sum of all the shifts that belong to that
        ///    axis.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Roll'.
        /// </param>
        /// <returns>
        ///    Has the same shape and size as the input. The elements are shifted
        ///    positively (towards larger indices) by the offsets of <c>shift</c> along the
        ///    dimensions of <c>axis</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The elements are shifted positively (towards larger indices) by the offset of
        ///    <c>shift</c> along the dimension of <c>axis</c>. Negative <c>shift</c> values will shift
        ///    elements in the opposite direction. Elements that roll passed the last position
        ///    will wrap around to the first and vice versa. Multiple shifts along multiple
        ///    axes may be specified.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # 't' is [0, 1, 2, 3, 4]
        ///    roll(t, shift=2, axis=0) ==&amp;gt; [3, 4, 0, 1, 2]
        ///    
        ///    # shifting along multiple dimensions
        ///    # 't' is [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]
        ///    roll(t, shift=[1, -2], axis=[0, 1]) ==&amp;gt; [[7, 8, 9, 5, 6], [2, 3, 4, 0, 1]]
        ///    
        ///    # shifting along the same axis multiple times
        ///    # 't' is [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]
        ///    roll(t, shift=[2, -3], axis=[1, 1]) ==&amp;gt; [[1, 2, 3, 4, 0], [6, 7, 8, 9, 5]]
        ///   </code>
        /// </remarks>
        public static Tensor roll (Tensor input, Tensor shift, Tensor axis, string name = "Roll")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["shift"] = shift;
            dict["axis"] = axis;
            var op = _op_def_lib._apply_op_helper("Roll", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Rounds the values of a tensor to the nearest integer, element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Round'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Rounds half to even.  Also known as bankers rounding. If you want to round
        ///    according to the current system rounding mode use std::cint.
        /// </remarks>
        public static Tensor round (Tensor x, string name = "Round")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Round", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Perform batches of RPC requests.
        /// </summary>
        /// <param name="address">
        ///    <c>0-D</c> or <c>1-D</c>.  The address (i.e. host_name:port) of the RPC server.
        ///    If this tensor has more than 1 element, then multiple parallel rpc requests
        ///    are sent.  This argument broadcasts with <c>method</c> and <c>request</c>.
        /// </param>
        /// <param name="method">
        ///    <c>0-D</c> or <c>1-D</c>.  The method address on the RPC server.
        ///    If this tensor has more than 1 element, then multiple parallel rpc requests
        ///    are sent.  This argument broadcasts with <c>address</c> and <c>request</c>.
        /// </param>
        /// <param name="request">
        ///    <c>0-D</c> or <c>1-D</c>.  Serialized proto strings: the rpc request argument.
        ///    If this tensor has more than 1 element, then multiple parallel rpc requests
        ///    are sent.  This argument broadcasts with <c>address</c> and <c>method</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Rpc'.
        /// </param>
        /// <param name="protocol">
        ///    RPC protocol to use.  Empty string means use the default protocol.
        ///    Options include 'grpc'.
        /// </param>
        /// <param name="fail_fast">
        ///    <c>boolean</c>. If <c>true</c> (default), then failures to connect
        ///    (i.e., the server does not immediately respond) cause an RPC failure.
        /// </param>
        /// <param name="timeout_in_ms">
        ///    <c>int</c>. If <c>0</c> (default), then the kernel will run the RPC
        ///    request and only time out if the RPC deadline passes or the session times out.
        ///    If this value is greater than <c>0</c>, then the op will raise an exception if
        ///    the RPC takes longer than <c>timeout_in_ms</c>.
        /// </param>
        /// <returns>
        ///    Same shape as <c>request</c>. Serialized proto strings: the rpc responses.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op asynchronously performs either a single RPC request, or a batch
        ///    of requests.  RPC requests are defined by three main parameters:
        ///    
        ///    - <c>address</c> (the host+port or BNS address of the request)
        ///    - <c>method</c> (the RPC method name for the request)
        ///    - <c>request</c> (the serialized proto string, or vector of strings,
        ///    of the RPC request argument).
        ///    
        ///    For example, if you have an RPC service running on port localhost:2345,
        ///    and its interface is configured with the following proto declaration:
        ///    
        ///   <code>
        ///    service MyService {
        ///    rpc MyMethod(MyRequestProto) returns (MyResponseProto) {
        ///    }
        ///    };
        ///   </code>
        ///    
        ///    then call this op with arguments:
        ///    
        ///   <code>
        ///    address = "localhost:2345"
        ///    method = "MyService/MyMethod"
        ///   </code>
        ///    
        ///    The <c>request</c> tensor is a string tensor representing serialized <c>MyRequestProto</c>
        ///    strings; and the output string tensor <c>response</c> will have the same shape
        ///    and contain (upon successful completion) corresponding serialized
        ///    <c>MyResponseProto</c> strings.
        ///    
        ///    For example, to send a single, empty, <c>MyRequestProto</c>, call
        ///    this op with <c>request = ""</c>.  To send 5 **parallel** empty requests,
        ///    call this op with <c>request = ["", "", "", "", ""]</c>.
        ///    
        ///    More generally, one can create a batch of <c>MyRequestProto</c> serialized protos
        ///    from regular batched tensors using the <c>encode_proto</c> op, and convert
        ///    the response <c>MyResponseProto</c> serialized protos to batched tensors
        ///    using the <c>decode_proto</c> op.
        ///    
        ///    **NOTE** Working with serialized proto strings is faster than instantiating
        ///    actual proto objects in memory, so no performance degradation is expected
        ///    compared to writing custom kernels for this workflow.
        ///    
        ///    If the connection fails or the remote worker returns an error
        ///    status, the op reraises this exception locally.
        ///    
        ///    See the <c>TryRpc</c> op if you prefer to handle RPC failures manually in the graph.
        /// </remarks>
        public static Tensor rpc (Tensor address, Tensor method, Tensor request, string protocol = null, bool? fail_fast = null, int? timeout_in_ms = null, string name = "Rpc")
        {
            var dict = new Dictionary<string, object>();
            dict["address"] = address;
            dict["method"] = method;
            dict["request"] = request;
            if (protocol != null)
                dict["protocol"] = protocol;
            if (fail_fast.HasValue)
                dict["fail_fast"] = fail_fast.Value;
            if (timeout_in_ms.HasValue)
                dict["timeout_in_ms"] = timeout_in_ms.Value;
            var op = _op_def_lib._apply_op_helper("Rpc", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes reciprocal of square root of x element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Rsqrt'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    I.e., \\(y = 1 / \sqrt{x}\\).
        /// </remarks>
        public static Tensor rsqrt (Tensor x, string name = "Rsqrt")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Rsqrt", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradient for the rsqrt of <c>x</c> wrt its input.
        /// </summary>
        /// <param name="y">
        /// </param>
        /// <param name="dy">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'RsqrtGrad'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Specifically, <c>grad = dy * -0.5 * y^3</c>, where <c>y = rsqrt(x)</c>, and <c>dy</c>
        ///    is the corresponding input gradient.
        /// </remarks>
        public static Tensor rsqrt_grad (Tensor y, Tensor dy, string name = "RsqrtGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["y"] = y;
            dict["dy"] = dy;
            var op = _op_def_lib._apply_op_helper("RsqrtGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Generate a single randomly distorted bounding box for an image.
        /// </summary>
        /// <param name="image_size">
        ///    1-D, containing <c>[height, width, channels]</c>.
        /// </param>
        /// <param name="bounding_boxes">
        ///    3-D with shape <c>[batch, N, 4]</c> describing the N bounding boxes
        ///    associated with the image.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SampleDistortedBoundingBox'.
        /// </param>
        /// <param name="seed">
        ///    If either <c>seed</c> or <c>seed2</c> are set to non-zero, the random number
        ///    generator is seeded by the given <c>seed</c>.  Otherwise, it is seeded by a random
        ///    seed.
        /// </param>
        /// <param name="seed2">
        ///    A second seed to avoid seed collision.
        /// </param>
        /// <param name="min_object_covered">
        ///    The cropped area of the image must contain at least this
        ///    fraction of any bounding box supplied. The value of this parameter should be
        ///    non-negative. In the case of 0, the cropped area does not need to overlap
        ///    any of the bounding boxes supplied.
        /// </param>
        /// <param name="aspect_ratio_range">
        ///    The cropped area of the image must have an aspect ratio =
        ///    width / height within this range.
        /// </param>
        /// <param name="area_range">
        ///    The cropped area of the image must contain a fraction of the
        ///    supplied image within this range.
        /// </param>
        /// <param name="max_attempts">
        ///    Number of attempts at generating a cropped region of the image
        ///    of the specified constraints. After <c>max_attempts</c> failures, return the entire
        ///    image.
        /// </param>
        /// <param name="use_image_if_no_bounding_boxes">
        ///    Controls behavior if no bounding boxes supplied.
        ///    If true, assume an implicit bounding box covering the whole input. If false,
        ///    raise an error.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    begin : 1-D, containing <c>[offset_height, offset_width, 0]</c>. Provide as input to
        ///    <c>tf.slice</c>.
        ///    size : 1-D, containing <c>[target_height, target_width, -1]</c>. Provide as input to
        ///    <c>tf.slice</c>.
        ///    bboxes : 3-D with shape <c>[1, 1, 4]</c> containing the distorted bounding box.
        ///    Provide as input to <c>tf.image.draw_bounding_boxes</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Bounding box annotations are often supplied in addition to ground-truth labels
        ///    in image recognition or object localization tasks. A common technique for
        ///    training such a system is to randomly distort an image while preserving
        ///    its content, i.e. *data augmentation*. This Op outputs a randomly distorted
        ///    localization of an object, i.e. bounding box, given an <c>image_size</c>,
        ///    <c>bounding_boxes</c> and a series of constraints.
        ///    
        ///    The output of this Op is a single bounding box that may be used to crop the
        ///    original image. The output is returned as 3 tensors: <c>begin</c>, <c>size</c> and
        ///    <c>bboxes</c>. The first 2 tensors can be fed directly into <c>tf.slice</c> to crop the
        ///    image. The latter may be supplied to <c>tf.image.draw_bounding_boxes</c> to visualize
        ///    what the bounding box looks like.
        ///    
        ///    Bounding boxes are supplied and returned as <c>[y_min, x_min, y_max, x_max]</c>. The
        ///    bounding box coordinates are floats in <c>[0.0, 1.0]</c> relative to the width and
        ///    height of the underlying image.
        ///    
        ///    For example,
        ///    
        ///   <code>
        ///    # Generate a single distorted bounding box.
        ///    begin, size, bbox_for_draw = tf.image.sample_distorted_bounding_box(
        ///    tf.shape(image),
        ///    bounding_boxes=bounding_boxes)
        ///    
        ///    # Draw the bounding box in an image summary.
        ///    image_with_box = tf.image.draw_bounding_boxes(tf.expand_dims(image, 0),
        ///    bbox_for_draw)
        ///    tf.summary.image('images_with_box', image_with_box)
        ///    
        ///    # Employ the bounding box to distort the image.
        ///    distorted_image = tf.slice(image, begin, size)
        ///   </code>
        ///    
        ///    Note that if no bounding box information is available, setting
        ///    <c>use_image_if_no_bounding_boxes = true</c> will assume there is a single implicit
        ///    bounding box covering the whole image. If <c>use_image_if_no_bounding_boxes</c> is
        ///    false and no bounding boxes are supplied, an error is raised.
        /// </remarks>
        public static (Tensor begin, Tensor size, Tensor bboxes) sample_distorted_bounding_box (Tensor image_size, Tensor bounding_boxes, int? seed = null, int? seed2 = null, float? min_object_covered = null, float[] aspect_ratio_range = null, float[] area_range = null, int? max_attempts = null, bool? use_image_if_no_bounding_boxes = null, string name = "SampleDistortedBoundingBox")
        {
            var dict = new Dictionary<string, object>();
            dict["image_size"] = image_size;
            dict["bounding_boxes"] = bounding_boxes;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            if (min_object_covered.HasValue)
                dict["min_object_covered"] = min_object_covered.Value;
            if (aspect_ratio_range != null)
                dict["aspect_ratio_range"] = aspect_ratio_range;
            if (area_range != null)
                dict["area_range"] = area_range;
            if (max_attempts.HasValue)
                dict["max_attempts"] = max_attempts.Value;
            if (use_image_if_no_bounding_boxes.HasValue)
                dict["use_image_if_no_bounding_boxes"] = use_image_if_no_bounding_boxes.Value;
            var op = _op_def_lib._apply_op_helper("SampleDistortedBoundingBox", name: name, keywords: dict);
            int _idx = 0;
            var begin = op.outputs[_idx++];
            var size = op.outputs[_idx++];
            var bboxes = op.outputs[_idx++];
            return (begin, size, bboxes);
        }

        /// <summary>
        ///    Generate a single randomly distorted bounding box for an image.
        /// </summary>
        /// <param name="image_size">
        ///    1-D, containing <c>[height, width, channels]</c>.
        /// </param>
        /// <param name="bounding_boxes">
        ///    3-D with shape <c>[batch, N, 4]</c> describing the N bounding boxes
        ///    associated with the image.
        /// </param>
        /// <param name="min_object_covered">
        ///    The cropped area of the image must contain at least this
        ///    fraction of any bounding box supplied. The value of this parameter should be
        ///    non-negative. In the case of 0, the cropped area does not need to overlap
        ///    any of the bounding boxes supplied.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SampleDistortedBoundingBoxV2'.
        /// </param>
        /// <param name="seed">
        ///    If either <c>seed</c> or <c>seed2</c> are set to non-zero, the random number
        ///    generator is seeded by the given <c>seed</c>.  Otherwise, it is seeded by a random
        ///    seed.
        /// </param>
        /// <param name="seed2">
        ///    A second seed to avoid seed collision.
        /// </param>
        /// <param name="aspect_ratio_range">
        ///    The cropped area of the image must have an aspect ratio =
        ///    width / height within this range.
        /// </param>
        /// <param name="area_range">
        ///    The cropped area of the image must contain a fraction of the
        ///    supplied image within this range.
        /// </param>
        /// <param name="max_attempts">
        ///    Number of attempts at generating a cropped region of the image
        ///    of the specified constraints. After <c>max_attempts</c> failures, return the entire
        ///    image.
        /// </param>
        /// <param name="use_image_if_no_bounding_boxes">
        ///    Controls behavior if no bounding boxes supplied.
        ///    If true, assume an implicit bounding box covering the whole input. If false,
        ///    raise an error.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    begin : 1-D, containing <c>[offset_height, offset_width, 0]</c>. Provide as input to
        ///    <c>tf.slice</c>.
        ///    size : 1-D, containing <c>[target_height, target_width, -1]</c>. Provide as input to
        ///    <c>tf.slice</c>.
        ///    bboxes : 3-D with shape <c>[1, 1, 4]</c> containing the distorted bounding box.
        ///    Provide as input to <c>tf.image.draw_bounding_boxes</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Bounding box annotations are often supplied in addition to ground-truth labels
        ///    in image recognition or object localization tasks. A common technique for
        ///    training such a system is to randomly distort an image while preserving
        ///    its content, i.e. *data augmentation*. This Op outputs a randomly distorted
        ///    localization of an object, i.e. bounding box, given an <c>image_size</c>,
        ///    <c>bounding_boxes</c> and a series of constraints.
        ///    
        ///    The output of this Op is a single bounding box that may be used to crop the
        ///    original image. The output is returned as 3 tensors: <c>begin</c>, <c>size</c> and
        ///    <c>bboxes</c>. The first 2 tensors can be fed directly into <c>tf.slice</c> to crop the
        ///    image. The latter may be supplied to <c>tf.image.draw_bounding_boxes</c> to visualize
        ///    what the bounding box looks like.
        ///    
        ///    Bounding boxes are supplied and returned as <c>[y_min, x_min, y_max, x_max]</c>. The
        ///    bounding box coordinates are floats in <c>[0.0, 1.0]</c> relative to the width and
        ///    height of the underlying image.
        ///    
        ///    For example,
        ///    
        ///   <code>
        ///    # Generate a single distorted bounding box.
        ///    begin, size, bbox_for_draw = tf.image.sample_distorted_bounding_box(
        ///    tf.shape(image),
        ///    bounding_boxes=bounding_boxes)
        ///    
        ///    # Draw the bounding box in an image summary.
        ///    image_with_box = tf.image.draw_bounding_boxes(tf.expand_dims(image, 0),
        ///    bbox_for_draw)
        ///    tf.summary.image('images_with_box', image_with_box)
        ///    
        ///    # Employ the bounding box to distort the image.
        ///    distorted_image = tf.slice(image, begin, size)
        ///   </code>
        ///    
        ///    Note that if no bounding box information is available, setting
        ///    <c>use_image_if_no_bounding_boxes = true</c> will assume there is a single implicit
        ///    bounding box covering the whole image. If <c>use_image_if_no_bounding_boxes</c> is
        ///    false and no bounding boxes are supplied, an error is raised.
        /// </remarks>
        public static (Tensor begin, Tensor size, Tensor bboxes) sample_distorted_bounding_box_v2 (Tensor image_size, Tensor bounding_boxes, Tensor min_object_covered, int? seed = null, int? seed2 = null, float[] aspect_ratio_range = null, float[] area_range = null, int? max_attempts = null, bool? use_image_if_no_bounding_boxes = null, string name = "SampleDistortedBoundingBoxV2")
        {
            var dict = new Dictionary<string, object>();
            dict["image_size"] = image_size;
            dict["bounding_boxes"] = bounding_boxes;
            dict["min_object_covered"] = min_object_covered;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            if (aspect_ratio_range != null)
                dict["aspect_ratio_range"] = aspect_ratio_range;
            if (area_range != null)
                dict["area_range"] = area_range;
            if (max_attempts.HasValue)
                dict["max_attempts"] = max_attempts.Value;
            if (use_image_if_no_bounding_boxes.HasValue)
                dict["use_image_if_no_bounding_boxes"] = use_image_if_no_bounding_boxes.Value;
            var op = _op_def_lib._apply_op_helper("SampleDistortedBoundingBoxV2", name: name, keywords: dict);
            int _idx = 0;
            var begin = op.outputs[_idx++];
            var size = op.outputs[_idx++];
            var bboxes = op.outputs[_idx++];
            return (begin, size, bboxes);
        }

        /// <summary>
        ///    Saves the input tensors to disk.
        /// </summary>
        /// <param name="filename">
        ///    Must have a single element. The name of the file to which we write
        ///    the tensor.
        /// </param>
        /// <param name="tensor_names">
        ///    Shape <c>[N]</c>. The names of the tensors to be saved.
        /// </param>
        /// <param name="data">
        ///    <c>N</c> tensors to save.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Save'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    The size of <c>tensor_names</c> must match the number of tensors in <c>data</c>. <c>data[i]</c>
        ///    is written to <c>filename</c> with name <c>tensor_names[i]</c>.
        ///    
        ///    See also <c>SaveSlices</c>.
        /// </remarks>
        public static Operation save (Tensor filename, Tensor tensor_names, Tensor[] data, string name = "Save")
        {
            var dict = new Dictionary<string, object>();
            dict["filename"] = filename;
            dict["tensor_names"] = tensor_names;
            dict["data"] = data;
            var op = _op_def_lib._apply_op_helper("Save", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Saves input tensors slices to disk.
        /// </summary>
        /// <param name="filename">
        ///    Must have a single element. The name of the file to which we write the
        ///    tensor.
        /// </param>
        /// <param name="tensor_names">
        ///    Shape <c>[N]</c>. The names of the tensors to be saved.
        /// </param>
        /// <param name="shapes_and_slices">
        ///    Shape <c>[N]</c>.  The shapes and slice specifications to use when
        ///    saving the tensors.
        /// </param>
        /// <param name="data">
        ///    <c>N</c> tensors to save.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SaveSlices'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    This is like <c>Save</c> except that tensors can be listed in the saved file as being
        ///    a slice of a larger tensor.  <c>shapes_and_slices</c> specifies the shape of the
        ///    larger tensor and the slice that this tensor covers. <c>shapes_and_slices</c> must
        ///    have as many elements as <c>tensor_names</c>.
        ///    
        ///    Elements of the <c>shapes_and_slices</c> input must either be:
        ///    
        ///    *  The empty string, in which case the corresponding tensor is
        ///    saved normally.
        ///    *  A string of the form <c>dim0 dim1 ... dimN-1 slice-spec</c> where the
        ///    <c>dimI</c> are the dimensions of the larger tensor and <c>slice-spec</c>
        ///    specifies what part is covered by the tensor to save.
        ///    
        ///    <c>slice-spec</c> itself is a <c>:</c>-separated list: <c>slice0:slice1:...:sliceN-1</c>
        ///    where each <c>sliceI</c> is either:
        ///    
        ///    *  The string <c>-</c> meaning that the slice covers all indices of this dimension
        ///    *  <c>start,length</c> where <c>start</c> and <c>length</c> are integers.  In that
        ///    case the slice covers <c>length</c> indices starting at <c>start</c>.
        ///    
        ///    See also <c>Save</c>.
        /// </remarks>
        public static Operation save_slices (Tensor filename, Tensor tensor_names, Tensor shapes_and_slices, Tensor[] data, string name = "SaveSlices")
        {
            var dict = new Dictionary<string, object>();
            dict["filename"] = filename;
            dict["tensor_names"] = tensor_names;
            dict["shapes_and_slices"] = shapes_and_slices;
            dict["data"] = data;
            var op = _op_def_lib._apply_op_helper("SaveSlices", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Saves tensors in V2 checkpoint format.
        /// </summary>
        /// <param name="prefix">
        ///    Must have a single element. The prefix of the V2 checkpoint to which we
        ///    write the tensors.
        /// </param>
        /// <param name="tensor_names">
        ///    shape {N}. The names of the tensors to be saved.
        /// </param>
        /// <param name="shape_and_slices">
        ///    shape {N}.  The slice specs of the tensors to be saved.
        ///    Empty strings indicate that they are non-partitioned tensors.
        /// </param>
        /// <param name="tensors">
        ///    <c>N</c> tensors to save.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SaveV2'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    By default, saves the named tensors in full.  If the caller wishes to save
        ///    specific slices of full tensors, "shape_and_slices" should be non-empty strings
        ///    and correspondingly well-formed.
        /// </remarks>
        public static Operation save_v2 (Tensor prefix, Tensor tensor_names, Tensor shape_and_slices, Tensor[] tensors, string name = "SaveV2")
        {
            var dict = new Dictionary<string, object>();
            dict["prefix"] = prefix;
            dict["tensor_names"] = tensor_names;
            dict["shape_and_slices"] = shape_and_slices;
            dict["tensors"] = tensors;
            var op = _op_def_lib._apply_op_helper("SaveV2", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Outputs a <c>Summary</c> protocol buffer with scalar values.
        /// </summary>
        /// <param name="tags">
        ///    Tags for the summary.
        /// </param>
        /// <param name="values">
        ///    Same shape as <c>tags.  Values for the summary.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ScalarSummary'.
        /// </param>
        /// <returns>
        ///    Scalar.  Serialized <c>Summary</c> protocol buffer.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The input <c>tags</c> and <c>values</c> must have the same shape.  The generated summary
        ///    has a summary value for each tag-value pair in <c>tags</c> and <c>values</c>.
        /// </remarks>
        public static Tensor scalar_summary (Tensor tags, Tensor values, string name = "ScalarSummary")
        {
            var dict = new Dictionary<string, object>();
            dict["tags"] = tags;
            dict["values"] = values;
            var op = _op_def_lib._apply_op_helper("ScalarSummary", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Adds sparse updates to a variable reference.
        /// </summary>
        /// <param name="referecne">
        ///    Should be from a <c>Variable</c> node.
        /// </param>
        /// <param name="indices">
        ///    A tensor of indices into the first dimension of <c>ref</c>.
        /// </param>
        /// <param name="updates">
        ///    A tensor of updated values to add to <c>ref</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ScatterAdd'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, the addition will be protected by a lock;
        ///    otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    = Same as <c>ref</c>.  Returned as a convenience for operations that want
        ///    to use the updated values after the update is done.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation computes
        ///    
        ///    # Scalar indices
        ///    ref[indices, ...] += updates[...]
        ///    
        ///    # Vector indices (for each i)
        ///    ref[indices[i], ...] += updates[i, ...]
        ///    
        ///    # High rank indices (for each i, ..., j)
        ///    ref[indices[i, ..., j], ...] += updates[i, ..., j, ...]
        ///    
        ///    This operation outputs <c>ref</c> after the update is done.
        ///    This makes it easier to chain operations that need to use the reset value.
        ///    
        ///    Duplicate entries are handled correctly: if multiple <c>indices</c> reference
        ///    the same location, their contributions add.
        ///    
        ///    Requires <c>updates.shape = indices.shape + ref.shape[1:]</c> or <c>updates.shape = []</c>.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src="https://www.tensorflow.org/images/ScatterAdd.png" alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Tensor scatter_add (Tensor referecne, Tensor indices, Tensor updates, bool? use_locking = null, string name = "ScatterAdd")
        {
            var dict = new Dictionary<string, object>();
            dict["ref"] = referecne;
            dict["indices"] = indices;
            dict["updates"] = updates;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ScatterAdd", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Divides a variable reference by sparse updates.
        /// </summary>
        /// <param name="referecne">
        ///    Should be from a <c>Variable</c> node.
        /// </param>
        /// <param name="indices">
        ///    A tensor of indices into the first dimension of <c>ref</c>.
        /// </param>
        /// <param name="updates">
        ///    A tensor of values that <c>ref</c> is divided by.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ScatterDiv'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, the operation will be protected by a lock;
        ///    otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    = Same as <c>ref</c>.  Returned as a convenience for operations that want
        ///    to use the updated values after the update is done.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation computes
        ///    
        ///   <code>
        ///    # Scalar indices
        ///    ref[indices, ...] /= updates[...]
        ///    
        ///    # Vector indices (for each i)
        ///    ref[indices[i], ...] /= updates[i, ...]
        ///    
        ///    # High rank indices (for each i, ..., j)
        ///    ref[indices[i, ..., j], ...] /= updates[i, ..., j, ...]
        ///   </code>
        ///    
        ///    This operation outputs <c>ref</c> after the update is done.
        ///    This makes it easier to chain operations that need to use the reset value.
        ///    
        ///    Duplicate entries are handled correctly: if multiple <c>indices</c> reference
        ///    the same location, their contributions divide.
        ///    
        ///    Requires <c>updates.shape = indices.shape + ref.shape[1:]</c> or <c>updates.shape = []</c>.
        /// </remarks>
        public static Tensor scatter_div (Tensor referecne, Tensor indices, Tensor updates, bool? use_locking = null, string name = "ScatterDiv")
        {
            var dict = new Dictionary<string, object>();
            dict["ref"] = referecne;
            dict["indices"] = indices;
            dict["updates"] = updates;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ScatterDiv", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Reduces sparse updates into a variable reference using the <c>max</c> operation.
        /// </summary>
        /// <param name="referecne">
        ///    Should be from a <c>Variable</c> node.
        /// </param>
        /// <param name="indices">
        ///    A tensor of indices into the first dimension of <c>ref</c>.
        /// </param>
        /// <param name="updates">
        ///    A tensor of updated values to reduce into <c>ref</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ScatterMax'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, the update will be protected by a lock;
        ///    otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    = Same as <c>ref</c>.  Returned as a convenience for operations that want
        ///    to use the updated values after the update is done.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation computes
        ///    
        ///    # Scalar indices
        ///    ref[indices, ...] = max(ref[indices, ...], updates[...])
        ///    
        ///    # Vector indices (for each i)
        ///    ref[indices[i], ...] = max(ref[indices[i], ...], updates[i, ...])
        ///    
        ///    # High rank indices (for each i, ..., j)
        ///    ref[indices[i, ..., j], ...] = max(ref[indices[i, ..., j], ...], updates[i, ..., j, ...])
        ///    
        ///    This operation outputs <c>ref</c> after the update is done.
        ///    This makes it easier to chain operations that need to use the reset value.
        ///    
        ///    Duplicate entries are handled correctly: if multiple <c>indices</c> reference
        ///    the same location, their contributions combine.
        ///    
        ///    Requires <c>updates.shape = indices.shape + ref.shape[1:]</c> or <c>updates.shape = []</c>.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src="https://www.tensorflow.org/images/ScatterAdd.png" alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Tensor scatter_max (Tensor referecne, Tensor indices, Tensor updates, bool? use_locking = null, string name = "ScatterMax")
        {
            var dict = new Dictionary<string, object>();
            dict["ref"] = referecne;
            dict["indices"] = indices;
            dict["updates"] = updates;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ScatterMax", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Reduces sparse updates into a variable reference using the <c>min</c> operation.
        /// </summary>
        /// <param name="referecne">
        ///    Should be from a <c>Variable</c> node.
        /// </param>
        /// <param name="indices">
        ///    A tensor of indices into the first dimension of <c>ref</c>.
        /// </param>
        /// <param name="updates">
        ///    A tensor of updated values to reduce into <c>ref</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ScatterMin'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, the update will be protected by a lock;
        ///    otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    = Same as <c>ref</c>.  Returned as a convenience for operations that want
        ///    to use the updated values after the update is done.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation computes
        ///    
        ///    # Scalar indices
        ///    ref[indices, ...] = min(ref[indices, ...], updates[...])
        ///    
        ///    # Vector indices (for each i)
        ///    ref[indices[i], ...] = min(ref[indices[i], ...], updates[i, ...])
        ///    
        ///    # High rank indices (for each i, ..., j)
        ///    ref[indices[i, ..., j], ...] = min(ref[indices[i, ..., j], ...], updates[i, ..., j, ...])
        ///    
        ///    This operation outputs <c>ref</c> after the update is done.
        ///    This makes it easier to chain operations that need to use the reset value.
        ///    
        ///    Duplicate entries are handled correctly: if multiple <c>indices</c> reference
        ///    the same location, their contributions combine.
        ///    
        ///    Requires <c>updates.shape = indices.shape + ref.shape[1:]</c> or <c>updates.shape = []</c>.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src="https://www.tensorflow.org/images/ScatterAdd.png" alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Tensor scatter_min (Tensor referecne, Tensor indices, Tensor updates, bool? use_locking = null, string name = "ScatterMin")
        {
            var dict = new Dictionary<string, object>();
            dict["ref"] = referecne;
            dict["indices"] = indices;
            dict["updates"] = updates;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ScatterMin", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Multiplies sparse updates into a variable reference.
        /// </summary>
        /// <param name="referecne">
        ///    Should be from a <c>Variable</c> node.
        /// </param>
        /// <param name="indices">
        ///    A tensor of indices into the first dimension of <c>ref</c>.
        /// </param>
        /// <param name="updates">
        ///    A tensor of updated values to multiply to <c>ref</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ScatterMul'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, the operation will be protected by a lock;
        ///    otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    = Same as <c>ref</c>.  Returned as a convenience for operations that want
        ///    to use the updated values after the update is done.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation computes
        ///    
        ///   <code>
        ///    # Scalar indices
        ///    ref[indices, ...] *= updates[...]
        ///    
        ///    # Vector indices (for each i)
        ///    ref[indices[i], ...] *= updates[i, ...]
        ///    
        ///    # High rank indices (for each i, ..., j)
        ///    ref[indices[i, ..., j], ...] *= updates[i, ..., j, ...]
        ///   </code>
        ///    
        ///    This operation outputs <c>ref</c> after the update is done.
        ///    This makes it easier to chain operations that need to use the reset value.
        ///    
        ///    Duplicate entries are handled correctly: if multiple <c>indices</c> reference
        ///    the same location, their contributions multiply.
        ///    
        ///    Requires <c>updates.shape = indices.shape + ref.shape[1:]</c> or <c>updates.shape = []</c>.
        /// </remarks>
        public static Tensor scatter_mul (Tensor referecne, Tensor indices, Tensor updates, bool? use_locking = null, string name = "ScatterMul")
        {
            var dict = new Dictionary<string, object>();
            dict["ref"] = referecne;
            dict["indices"] = indices;
            dict["updates"] = updates;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ScatterMul", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Scatter <c>updates</c> into a new tensor according to <c>indices</c>.
        /// </summary>
        /// <param name="indices">
        ///    Index tensor.
        /// </param>
        /// <param name="updates">
        ///    Updates to scatter into output.
        /// </param>
        /// <param name="shape">
        ///    1-D. The shape of the resulting tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ScatterNd'.
        /// </param>
        /// <returns>
        ///    A new tensor with the given shape and updates applied according
        ///    to the indices.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Creates a new tensor by applying sparse <c>updates</c> to individual values or
        ///    slices within a tensor (initially zero for numeric, empty for string) of
        ///    the given <c>shape</c> according to indices.  This operator is the inverse of the
        ///    <c>tf.gather_nd</c> operator which extracts values or slices from a given tensor.
        ///    
        ///    If <c>indices</c> contains duplicates, then their updates are accumulated (summed).
        ///    
        ///    **WARNING**: The order in which updates are applied is nondeterministic, so the
        ///    output will be nondeterministic if <c>indices</c> contains duplicates -- because
        ///    of some numerical approximation issues, numbers summed in different order
        ///    may yield different results.
        ///    
        ///    <c>indices</c> is an integer tensor containing indices into a new tensor of shape
        ///    <c>shape</c>.  The last dimension of <c>indices</c> can be at most the rank of <c>shape</c>:
        ///    
        ///    indices.shape[-1] &amp;lt;= shape.rank
        ///    
        ///    The last dimension of <c>indices</c> corresponds to indices into elements
        ///    (if <c>indices.shape[-1] = shape.rank</c>) or slices
        ///    (if <c>indices.shape[-1] &amp;lt; shape.rank</c>) along dimension <c>indices.shape[-1]</c> of
        ///    <c>shape</c>.  <c>updates</c> is a tensor with shape
        ///    
        ///    indices.shape[:-1] + shape[indices.shape[-1]:]
        ///    
        ///    The simplest form of scatter is to insert individual elements in a tensor by
        ///    index. For example, say we want to insert 4 scattered elements in a rank-1
        ///    tensor with 8 elements.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src="https://www.tensorflow.org/images/ScatterNd1.png" alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        ///    
        ///    In Python, this scatter operation would look like this:
        ///    
        ///   <code>
        ///    indices = tf.constant([[4], [3], [1], [7]])
        ///    updates = tf.constant([9, 10, 11, 12])
        ///    shape = tf.constant([8])
        ///    scatter = tf.scatter_nd(indices, updates, shape)
        ///    with tf.Session() as sess:
        ///    print(sess.run(scatter))
        ///   </code>
        ///    
        ///    The resulting tensor would look like this:
        ///    
        ///    [0, 11, 0, 10, 9, 0, 0, 12]
        ///    
        ///    We can also, insert entire slices of a higher rank tensor all at once. For
        ///    example, if we wanted to insert two slices in the first dimension of a
        ///    rank-3 tensor with two matrices of new values.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src="https://www.tensorflow.org/images/ScatterNd2.png" alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        ///    
        ///    In Python, this scatter operation would look like this:
        ///    
        ///   <code>
        ///    indices = tf.constant([[0], [2]])
        ///    updates = tf.constant([[[5, 5, 5, 5], [6, 6, 6, 6],
        ///    [7, 7, 7, 7], [8, 8, 8, 8]],
        ///    [[5, 5, 5, 5], [6, 6, 6, 6],
        ///    [7, 7, 7, 7], [8, 8, 8, 8]]])
        ///    shape = tf.constant([4, 4, 4])
        ///    scatter = tf.scatter_nd(indices, updates, shape)
        ///    with tf.Session() as sess:
        ///    print(sess.run(scatter))
        ///   </code>
        ///    
        ///    The resulting tensor would look like this:
        ///    
        ///    [[[5, 5, 5, 5], [6, 6, 6, 6], [7, 7, 7, 7], [8, 8, 8, 8]],
        ///    [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]],
        ///    [[5, 5, 5, 5], [6, 6, 6, 6], [7, 7, 7, 7], [8, 8, 8, 8]],
        ///    [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]]
        ///    
        ///    Note that on CPU, if an out of bound index is found, an error is returned.
        ///    On GPU, if an out of bound index is found, the index is ignored.
        /// </remarks>
        public static Tensor scatter_nd (Tensor indices, Tensor updates, Tensor shape, string name = "ScatterNd")
        {
            var dict = new Dictionary<string, object>();
            dict["indices"] = indices;
            dict["updates"] = updates;
            dict["shape"] = shape;
            var op = _op_def_lib._apply_op_helper("ScatterNd", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Applies sparse addition between <c>updates</c> and individual values or slices
        /// </summary>
        /// <param name="referecne">
        ///    A mutable Tensor. Should be from a Variable node.
        /// </param>
        /// <param name="indices">
        ///    A Tensor. Must be one of the following types: int32, int64.
        ///    A tensor of indices into ref.
        /// </param>
        /// <param name="updates">
        ///    A Tensor. Must have the same type as ref. A tensor of updated values
        ///    to add to ref.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ScatterNdAdd'.
        /// </param>
        /// <param name="use_locking">
        ///    An optional bool. Defaults to True. If True, the assignment will
        ///    be protected by a lock; otherwise the behavior is undefined,
        ///    but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Same as ref. Returned as a convenience for operations that want
        ///    to use the updated values after the update is done.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    within a given variable according to <c>indices</c>.
        ///    
        ///    <c>ref</c> is a <c>Tensor</c> with rank <c>P</c> and <c>indices</c> is a <c>Tensor</c> of rank <c>Q</c>.
        ///    
        ///    <c>indices</c> must be integer tensor, containing indices into <c>ref</c>.
        ///    It must be shape <c>\\([d_0, ..., d_{Q-2}, K]\\)</c> where <c>0 &amp;lt; K &amp;lt;= P</c>.
        ///    
        ///    The innermost dimension of <c>indices</c> (with length <c>K</c>) corresponds to
        ///    indices into elements (if <c>K = P</c>) or slices (if <c>K &amp;lt; P</c>) along the <c>K</c>th
        ///    dimension of <c>ref</c>.
        ///    
        ///    <c>updates</c> is <c>Tensor</c> of rank <c>Q-1+P-K</c> with shape:
        ///    
        ///    $$[d_0, ..., d_{Q-2}, ref.shape[K], ..., ref.shape[P-1]].$$
        ///    
        ///    For example, say we want to add 4 scattered elements to a rank-1 tensor to 8
        ///    elements. In Python, that addition would look like this:
        ///    
        ///    ref = tf.Variable([1, 2, 3, 4, 5, 6, 7, 8])
        ///    indices = tf.constant([[4], [3], [1], [7]])
        ///    updates = tf.constant([9, 10, 11, 12])
        ///    add = tf.scatter_nd_add(ref, indices, updates)
        ///    with tf.Session() as sess:
        ///    print sess.run(add)
        ///    
        ///    The resulting update to ref would look like this:
        ///    
        ///    [1, 13, 3, 14, 14, 6, 7, 20]
        ///    
        ///    See <c>tf.scatter_nd</c> for more details about how to make updates to
        ///    slices.
        /// </remarks>
        public static Tensor scatter_nd_add (Tensor referecne, Tensor indices, Tensor updates, bool? use_locking = null, string name = "ScatterNdAdd")
        {
            var dict = new Dictionary<string, object>();
            dict["ref"] = referecne;
            dict["indices"] = indices;
            dict["updates"] = updates;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ScatterNdAdd", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Applies sparse addition to <c>input</c> using individual values or slices
        /// </summary>
        /// <param name="input">
        ///    A Tensor.
        /// </param>
        /// <param name="indices">
        ///    A Tensor. Must be one of the following types: <c>int32</c>, <c>int64</c>.
        ///    A tensor of indices into <c>input</c>.
        /// </param>
        /// <param name="updates">
        ///    A Tensor. Must have the same type as ref. A tensor of updated values
        ///    to add to <c>input</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ScatterNdNonAliasingAdd'.
        /// </param>
        /// <returns>
        ///    A <c>Tensor</c> with the same shape as <c>input</c>, containing values of <c>input</c>
        ///    updated with <c>updates</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    from <c>updates</c> according to indices <c>indices</c>.  The updates are non-aliasing:
        ///    <c>input</c> is only modified in-place if no other operations will use it.
        ///    Otherwise, a copy of <c>input</c> is made.  This operation has a gradient with
        ///    respect to both <c>input</c> and <c>updates</c>.
        ///    
        ///    <c>input</c> is a <c>Tensor</c> with rank <c>P</c> and <c>indices</c> is a <c>Tensor</c> of rank <c>Q</c>.
        ///    
        ///    <c>indices</c> must be integer tensor, containing indices into <c>input</c>.
        ///    It must be shape \\([d_0, ..., d_{Q-2}, K]\\) where <c>0 &amp;lt; K &amp;lt;= P</c>.
        ///    
        ///    The innermost dimension of <c>indices</c> (with length <c>K</c>) corresponds to
        ///    indices into elements (if <c>K = P</c>) or <c>(P-K)</c>-dimensional slices
        ///    (if <c>K &amp;lt; P</c>) along the <c>K</c>th dimension of <c>input</c>.
        ///    
        ///    <c>updates</c> is <c>Tensor</c> of rank <c>Q-1+P-K</c> with shape:
        ///    
        ///    $$[d_0, ..., d_{Q-2}, input.shape[K], ..., input.shape[P-1]].$$
        ///    
        ///    For example, say we want to add 4 scattered elements to a rank-1 tensor to 8
        ///    elements. In Python, that addition would look like this:
        ///    
        ///    input = tf.constant([1, 2, 3, 4, 5, 6, 7, 8])
        ///    indices = tf.constant([[4], [3], [1], [7]])
        ///    updates = tf.constant([9, 10, 11, 12])
        ///    output = tf.scatter_nd_non_aliasing_add(input, indices, updates)
        ///    with tf.Session() as sess:
        ///    print(sess.run(output))
        ///    
        ///    The resulting value <c>output</c> would look like this:
        ///    
        ///    [1, 13, 3, 14, 14, 6, 7, 20]
        ///    
        ///    See <c>tf.scatter_nd</c> for more details about how to make updates to slices.
        /// </remarks>
        public static Tensor scatter_nd_non_aliasing_add (Tensor input, Tensor indices, Tensor updates, string name = "ScatterNdNonAliasingAdd")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["indices"] = indices;
            dict["updates"] = updates;
            var op = _op_def_lib._apply_op_helper("ScatterNdNonAliasingAdd", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Applies sparse subtraction between <c>updates</c> and individual values or slices
        /// </summary>
        /// <param name="referecne">
        ///    A mutable Tensor. Should be from a Variable node.
        /// </param>
        /// <param name="indices">
        ///    A Tensor. Must be one of the following types: int32, int64.
        ///    A tensor of indices into ref.
        /// </param>
        /// <param name="updates">
        ///    A Tensor. Must have the same type as ref. A tensor of updated values
        ///    to subtract from ref.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ScatterNdSub'.
        /// </param>
        /// <param name="use_locking">
        ///    An optional bool. Defaults to True. If True, the assignment will
        ///    be protected by a lock; otherwise the behavior is undefined,
        ///    but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Same as ref. Returned as a convenience for operations that want
        ///    to use the updated values after the update is done.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    within a given variable according to <c>indices</c>.
        ///    
        ///    <c>ref</c> is a <c>Tensor</c> with rank <c>P</c> and <c>indices</c> is a <c>Tensor</c> of rank <c>Q</c>.
        ///    
        ///    <c>indices</c> must be integer tensor, containing indices into <c>ref</c>.
        ///    It must be shape \\([d_0, ..., d_{Q-2}, K]\\) where <c>0 &amp;lt; K &amp;lt;= P</c>.
        ///    
        ///    The innermost dimension of <c>indices</c> (with length <c>K</c>) corresponds to
        ///    indices into elements (if <c>K = P</c>) or slices (if <c>K &amp;lt; P</c>) along the <c>K</c>th
        ///    dimension of <c>ref</c>.
        ///    
        ///    <c>updates</c> is <c>Tensor</c> of rank <c>Q-1+P-K</c> with shape:
        ///    
        ///    $$[d_0, ..., d_{Q-2}, ref.shape[K], ..., ref.shape[P-1]].$$
        ///    
        ///    For example, say we want to subtract 4 scattered elements from a rank-1 tensor
        ///    with 8 elements. In Python, that subtraction would look like this:
        ///    
        ///    ref = tf.Variable([1, 2, 3, 4, 5, 6, 7, 8])
        ///    indices = tf.constant([[4], [3], [1], [7]])
        ///    updates = tf.constant([9, 10, 11, 12])
        ///    sub = tf.scatter_nd_sub(ref, indices, updates)
        ///    with tf.Session() as sess:
        ///    print sess.run(sub)
        ///    
        ///    The resulting update to ref would look like this:
        ///    
        ///    [1, -9, 3, -6, -4, 6, 7, -4]
        ///    
        ///    See <c>tf.scatter_nd</c> for more details about how to make updates to
        ///    slices.
        /// </remarks>
        public static Tensor scatter_nd_sub (Tensor referecne, Tensor indices, Tensor updates, bool? use_locking = null, string name = "ScatterNdSub")
        {
            var dict = new Dictionary<string, object>();
            dict["ref"] = referecne;
            dict["indices"] = indices;
            dict["updates"] = updates;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ScatterNdSub", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Applies sparse <c>updates</c> to individual values or slices within a given
        /// </summary>
        /// <param name="referecne">
        ///    A mutable Tensor. Should be from a Variable node.
        /// </param>
        /// <param name="indices">
        ///    A Tensor. Must be one of the following types: int32, int64.
        ///    A tensor of indices into ref.
        /// </param>
        /// <param name="updates">
        ///    A Tensor. Must have the same type as ref. A tensor of updated
        ///    values to add to ref.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ScatterNdUpdate'.
        /// </param>
        /// <param name="use_locking">
        ///    An optional bool. Defaults to True. If True, the assignment will
        ///    be protected by a lock; otherwise the behavior is undefined,
        ///    but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Same as ref. Returned as a convenience for operations that want to
        ///    use the updated values after the update is done.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    variable according to <c>indices</c>.
        ///    
        ///    <c>ref</c> is a <c>Tensor</c> with rank <c>P</c> and <c>indices</c> is a <c>Tensor</c> of rank <c>Q</c>.
        ///    
        ///    <c>indices</c> must be integer tensor, containing indices into <c>ref</c>.
        ///    It must be shape \\([d_0, ..., d_{Q-2}, K]\\) where <c>0 &amp;lt; K &amp;lt;= P</c>.
        ///    
        ///    The innermost dimension of <c>indices</c> (with length <c>K</c>) corresponds to
        ///    indices into elements (if <c>K = P</c>) or slices (if <c>K &amp;lt; P</c>) along the <c>K</c>th
        ///    dimension of <c>ref</c>.
        ///    
        ///    <c>updates</c> is <c>Tensor</c> of rank <c>Q-1+P-K</c> with shape:
        ///    
        ///    $$[d_0, ..., d_{Q-2}, ref.shape[K], ..., ref.shape[P-1]].$$
        ///    
        ///    For example, say we want to update 4 scattered elements to a rank-1 tensor to
        ///    8 elements. In Python, that update would look like this:
        ///    
        ///   <code>
        ///    ref = tf.Variable([1, 2, 3, 4, 5, 6, 7, 8])
        ///    indices = tf.constant([[4], [3], [1] ,[7]])
        ///    updates = tf.constant([9, 10, 11, 12])
        ///    update = tf.scatter_nd_update(ref, indices, updates)
        ///    with tf.Session() as sess:
        ///    print sess.run(update)
        ///   </code>
        ///    
        ///    The resulting update to ref would look like this:
        ///    
        ///    [1, 11, 3, 10, 9, 6, 7, 12]
        ///    
        ///    See <c>tf.scatter_nd</c> for more details about how to make updates to
        ///    slices.
        ///    
        ///    See also <c>tf.scatter_update</c> and <c>tf.batch_scatter_update</c>.
        /// </remarks>
        public static Tensor scatter_nd_update (Tensor referecne, Tensor indices, Tensor updates, bool? use_locking = null, string name = "ScatterNdUpdate")
        {
            var dict = new Dictionary<string, object>();
            dict["ref"] = referecne;
            dict["indices"] = indices;
            dict["updates"] = updates;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ScatterNdUpdate", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Subtracts sparse updates to a variable reference.
        /// </summary>
        /// <param name="referecne">
        ///    Should be from a <c>Variable</c> node.
        /// </param>
        /// <param name="indices">
        ///    A tensor of indices into the first dimension of <c>ref</c>.
        /// </param>
        /// <param name="updates">
        ///    A tensor of updated values to subtract from <c>ref</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ScatterSub'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, the subtraction will be protected by a lock;
        ///    otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    = Same as <c>ref</c>.  Returned as a convenience for operations that want
        ///    to use the updated values after the update is done.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///   <code>
        ///    # Scalar indices
        ///    ref[indices, ...] -= updates[...]
        ///    
        ///    # Vector indices (for each i)
        ///    ref[indices[i], ...] -= updates[i, ...]
        ///    
        ///    # High rank indices (for each i, ..., j)
        ///    ref[indices[i, ..., j], ...] -= updates[i, ..., j, ...]
        ///   </code>
        ///    
        ///    This operation outputs <c>ref</c> after the update is done.
        ///    This makes it easier to chain operations that need to use the reset value.
        ///    
        ///    Duplicate entries are handled correctly: if multiple <c>indices</c> reference
        ///    the same location, their (negated) contributions add.
        ///    
        ///    Requires <c>updates.shape = indices.shape + ref.shape[1:]</c> or <c>updates.shape = []</c>.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src="https://www.tensorflow.org/images/ScatterSub.png" alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Tensor scatter_sub (Tensor referecne, Tensor indices, Tensor updates, bool? use_locking = null, string name = "ScatterSub")
        {
            var dict = new Dictionary<string, object>();
            dict["ref"] = referecne;
            dict["indices"] = indices;
            dict["updates"] = updates;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ScatterSub", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Applies sparse updates to a variable reference.
        /// </summary>
        /// <param name="referecne">
        ///    Should be from a <c>Variable</c> node.
        /// </param>
        /// <param name="indices">
        ///    A tensor of indices into the first dimension of <c>ref</c>.
        /// </param>
        /// <param name="updates">
        ///    A tensor of updated values to store in <c>ref</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ScatterUpdate'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, the assignment will be protected by a lock;
        ///    otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    = Same as <c>ref</c>.  Returned as a convenience for operations that want
        ///    to use the updated values after the update is done.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation computes
        ///    
        ///   <code>
        ///    # Scalar indices
        ///    ref[indices, ...] = updates[...]
        ///    
        ///    # Vector indices (for each i)
        ///    ref[indices[i], ...] = updates[i, ...]
        ///    
        ///    # High rank indices (for each i, ..., j)
        ///    ref[indices[i, ..., j], ...] = updates[i, ..., j, ...]
        ///   </code>
        ///    
        ///    This operation outputs <c>ref</c> after the update is done.
        ///    This makes it easier to chain operations that need to use the reset value.
        ///    
        ///    If values in <c>ref</c> is to be updated more than once, because there are
        ///    duplicate entries in <c>indices</c>, the order at which the updates happen
        ///    for each value is undefined.
        ///    
        ///    Requires <c>updates.shape = indices.shape + ref.shape[1:]</c> or <c>updates.shape = []</c>.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src="https://www.tensorflow.org/images/ScatterUpdate.png" alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        ///    
        ///    See also <c>tf.batch_scatter_update</c> and <c>tf.scatter_nd_update</c>.
        /// </remarks>
        public static Tensor scatter_update (Tensor referecne, Tensor indices, Tensor updates, bool? use_locking = null, string name = "ScatterUpdate")
        {
            var dict = new Dictionary<string, object>();
            dict["ref"] = referecne;
            dict["indices"] = indices;
            dict["updates"] = updates;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("ScatterUpdate", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes fingerprints of the input strings.
        /// </summary>
        /// <param name="input">
        ///    vector of strings to compute fingerprints on.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SdcaFprint'.
        /// </param>
        /// <returns>
        ///    a (N,2) shaped matrix where N is the number of elements in the input
        ///    vector. Each row contains the low and high parts of the fingerprint.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor sdca_fprint (Tensor input, string name = "SdcaFprint")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("SdcaFprint", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Distributed version of Stochastic Dual Coordinate Ascent (SDCA) optimizer for
        /// </summary>
        /// <param name="sparse_example_indices">
        ///    a list of vectors which contain example indices.
        /// </param>
        /// <param name="sparse_feature_indices">
        ///    a list of vectors which contain feature indices.
        /// </param>
        /// <param name="sparse_feature_values">
        ///    a list of vectors which contains feature value
        ///    associated with each feature group.
        /// </param>
        /// <param name="dense_features">
        ///    a list of matrices which contains the dense feature values.
        /// </param>
        /// <param name="example_weights">
        ///    a vector which contains the weight associated with each
        ///    example.
        /// </param>
        /// <param name="example_labels">
        ///    a vector which contains the label/target associated with each
        ///    example.
        /// </param>
        /// <param name="sparse_indices">
        ///    a list of vectors where each value is the indices which has
        ///    corresponding weights in sparse_weights. This field maybe omitted for the
        ///    dense approach.
        /// </param>
        /// <param name="sparse_weights">
        ///    a list of vectors where each value is the weight associated with
        ///    a sparse feature group.
        /// </param>
        /// <param name="dense_weights">
        ///    a list of vectors where the values are the weights associated
        ///    with a dense feature group.
        /// </param>
        /// <param name="example_state_data">
        ///    a list of vectors containing the example state data.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SdcaOptimizer'.
        /// </param>
        /// <param name="loss_type">
        ///    Optional argument
        ///    Type of the primal loss. Currently SdcaSolver supports logistic,
        ///    squared and hinge losses.
        /// </param>
        /// <param name="l1">
        ///    Optional argument
        ///    Symmetric l1 regularization strength.
        /// </param>
        /// <param name="l2">
        ///    Optional argument
        ///    Symmetric l2 regularization strength.
        /// </param>
        /// <param name="num_loss_partitions">
        ///    Optional argument
        ///    Number of partitions of the global loss function.
        /// </param>
        /// <param name="num_inner_iterations">
        ///    Optional argument
        ///    Number of iterations per mini-batch.
        /// </param>
        /// <param name="adaptative">
        ///    Whether to use Adaptive SDCA for the inner loop.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    out_example_state_data : a list of vectors containing the updated example state
        ///    data.
        ///    out_delta_sparse_weights : a list of vectors where each value is the delta
        ///    weights associated with a sparse feature group.
        ///    out_delta_dense_weights : a list of vectors where the values are the delta
        ///    weights associated with a dense feature group.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    linear models with L1 + L2 regularization. As global optimization objective is
        ///    strongly-convex, the optimizer optimizes the dual objective at each step. The
        ///    optimizer applies each update one example at a time. Examples are sampled
        ///    uniformly, and the optimizer is learning rate free and enjoys linear convergence
        ///    rate.
        ///    
        ///    [Proximal Stochastic Dual Coordinate Ascent](http://arxiv.org/pdf/1211.2717v1.pdf).&amp;lt;br&amp;gt;
        ///    Shai Shalev-Shwartz, Tong Zhang. 2012
        ///    
        ///    $$Loss Objective = \sum f_{i} (wx_{i}) + (l2 / 2) * |w|^2 + l1 * |w|$$
        ///    
        ///    [Adding vs. Averaging in Distributed Primal-Dual Optimization](http://arxiv.org/abs/1502.03508).&amp;lt;br&amp;gt;
        ///    Chenxin Ma, Virginia Smith, Martin Jaggi, Michael I. Jordan,
        ///    Peter Richtarik, Martin Takac. 2015
        ///    
        ///    [Stochastic Dual Coordinate Ascent with Adaptive Probabilities](https://arxiv.org/abs/1502.08053).&amp;lt;br&amp;gt;
        ///    Dominik Csiba, Zheng Qu, Peter Richtarik. 2015
        /// </remarks>
        public static (Tensor out_example_state_data, Tensor[] out_delta_sparse_weights, Tensor[] out_delta_dense_weights) sdca_optimizer (Tensor[] sparse_example_indices, Tensor[] sparse_feature_indices, Tensor[] sparse_feature_values, Tensor[] dense_features, Tensor example_weights, Tensor example_labels, Tensor[] sparse_indices, Tensor[] sparse_weights, Tensor[] dense_weights, Tensor example_state_data, string loss_type, float l1, float l2, int num_loss_partitions, int num_inner_iterations, bool? adaptative = null, string name = "SdcaOptimizer")
        {
            var dict = new Dictionary<string, object>();
            dict["sparse_example_indices"] = sparse_example_indices;
            dict["sparse_feature_indices"] = sparse_feature_indices;
            dict["sparse_feature_values"] = sparse_feature_values;
            dict["dense_features"] = dense_features;
            dict["example_weights"] = example_weights;
            dict["example_labels"] = example_labels;
            dict["sparse_indices"] = sparse_indices;
            dict["sparse_weights"] = sparse_weights;
            dict["dense_weights"] = dense_weights;
            dict["example_state_data"] = example_state_data;
            dict["loss_type"] = loss_type;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["num_loss_partitions"] = num_loss_partitions;
            dict["num_inner_iterations"] = num_inner_iterations;
            if (adaptative.HasValue)
                dict["adaptative"] = adaptative.Value;
            var op = _op_def_lib._apply_op_helper("SdcaOptimizer", name: name, keywords: dict);
            int _idx = 0;
            var out_example_state_data = op.outputs[_idx++];
            var out_delta_sparse_weights = Enumerable.Range(0, op.OutputListLength("out_delta_sparse_weights")).Select(_ => op.outputs[_idx++]).ToArray();
            var out_delta_dense_weights = Enumerable.Range(0, op.OutputListLength("out_delta_dense_weights")).Select(_ => op.outputs[_idx++]).ToArray();
            return (out_example_state_data, out_delta_sparse_weights, out_delta_dense_weights);
        }

        /// <summary>
        ///    Applies L1 regularization shrink step on the parameters.
        /// </summary>
        /// <param name="weights">
        ///    a list of vectors where each value is the weight associated with a
        ///    feature group.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SdcaShrinkL1'.
        /// </param>
        /// <param name="l1">
        ///    Optional argument
        ///    Symmetric l1 regularization strength.
        /// </param>
        /// <param name="l2">
        ///    Optional argument
        ///    Symmetric l2 regularization strength. Should be a positive float.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation sdca_shrink_l1 (Tensor[] weights, float l1, float l2, string name = "SdcaShrinkL1")
        {
            var dict = new Dictionary<string, object>();
            dict["weights"] = weights;
            dict["l1"] = l1;
            dict["l2"] = l2;
            var op = _op_def_lib._apply_op_helper("SdcaShrinkL1", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Computes the maximum along segments of a tensor.
        /// </summary>
        /// <param name="data">
        /// </param>
        /// <param name="segment_ids">
        ///    A 1-D tensor whose size is equal to the size of <c>data</c>'s
        ///    first dimension.  Values should be sorted and can be repeated.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SegmentMax'.
        /// </param>
        /// <returns>
        ///    Has same shape as data, except for dimension 0 which
        ///    has size <c>k</c>, the number of segments.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Read
        ///    [the section on segmentation](https://tensorflow.org/api_guides/python/math_ops#Segmentation)
        ///    for an explanation of segments.
        ///    
        ///    Computes a tensor such that
        ///    \\(output_i = \max_j(data_j)\\) where <c>max</c> is over <c>j</c> such
        ///    that <c>segment_ids[j] == i</c>.
        ///    
        ///    If the max is empty for a given segment ID <c>i</c>, <c>output[i] = 0</c>.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src="https://www.tensorflow.org/images/SegmentMax.png" alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Tensor segment_max (Tensor data, Tensor segment_ids, string name = "SegmentMax")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            dict["segment_ids"] = segment_ids;
            var op = _op_def_lib._apply_op_helper("SegmentMax", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the mean along segments of a tensor.
        /// </summary>
        /// <param name="data">
        /// </param>
        /// <param name="segment_ids">
        ///    A 1-D tensor whose size is equal to the size of <c>data</c>'s
        ///    first dimension.  Values should be sorted and can be repeated.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SegmentMean'.
        /// </param>
        /// <returns>
        ///    Has same shape as data, except for dimension 0 which
        ///    has size <c>k</c>, the number of segments.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Read
        ///    [the section on segmentation](https://tensorflow.org/api_guides/python/math_ops#Segmentation)
        ///    for an explanation of segments.
        ///    
        ///    Computes a tensor such that
        ///    \\(output_i = \frac{\sum_j data_j}{N}\\) where <c>mean</c> is
        ///    over <c>j</c> such that <c>segment_ids[j] == i</c> and <c>N</c> is the total number of
        ///    values summed.
        ///    
        ///    If the mean is empty for a given segment ID <c>i</c>, <c>output[i] = 0</c>.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src="https://www.tensorflow.org/images/SegmentMean.png" alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Tensor segment_mean (Tensor data, Tensor segment_ids, string name = "SegmentMean")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            dict["segment_ids"] = segment_ids;
            var op = _op_def_lib._apply_op_helper("SegmentMean", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the minimum along segments of a tensor.
        /// </summary>
        /// <param name="data">
        /// </param>
        /// <param name="segment_ids">
        ///    A 1-D tensor whose size is equal to the size of <c>data</c>'s
        ///    first dimension.  Values should be sorted and can be repeated.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SegmentMin'.
        /// </param>
        /// <returns>
        ///    Has same shape as data, except for dimension 0 which
        ///    has size <c>k</c>, the number of segments.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Read
        ///    [the section on segmentation](https://tensorflow.org/api_guides/python/math_ops#Segmentation)
        ///    for an explanation of segments.
        ///    
        ///    Computes a tensor such that
        ///    \\(output_i = \min_j(data_j)\\) where <c>min</c> is over <c>j</c> such
        ///    that <c>segment_ids[j] == i</c>.
        ///    
        ///    If the min is empty for a given segment ID <c>i</c>, <c>output[i] = 0</c>.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src="https://www.tensorflow.org/images/SegmentMin.png" alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Tensor segment_min (Tensor data, Tensor segment_ids, string name = "SegmentMin")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            dict["segment_ids"] = segment_ids;
            var op = _op_def_lib._apply_op_helper("SegmentMin", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the product along segments of a tensor.
        /// </summary>
        /// <param name="data">
        /// </param>
        /// <param name="segment_ids">
        ///    A 1-D tensor whose size is equal to the size of <c>data</c>'s
        ///    first dimension.  Values should be sorted and can be repeated.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SegmentProd'.
        /// </param>
        /// <returns>
        ///    Has same shape as data, except for dimension 0 which
        ///    has size <c>k</c>, the number of segments.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Read
        ///    [the section on segmentation](https://tensorflow.org/api_guides/python/math_ops#Segmentation)
        ///    for an explanation of segments.
        ///    
        ///    Computes a tensor such that
        ///    \\(output_i = \prod_j data_j\\) where the product is over <c>j</c> such
        ///    that <c>segment_ids[j] == i</c>.
        ///    
        ///    If the product is empty for a given segment ID <c>i</c>, <c>output[i] = 1</c>.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src="https://www.tensorflow.org/images/SegmentProd.png" alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Tensor segment_prod (Tensor data, Tensor segment_ids, string name = "SegmentProd")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            dict["segment_ids"] = segment_ids;
            var op = _op_def_lib._apply_op_helper("SegmentProd", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the sum along segments of a tensor.
        /// </summary>
        /// <param name="data">
        /// </param>
        /// <param name="segment_ids">
        ///    A 1-D tensor whose size is equal to the size of <c>data</c>'s
        ///    first dimension.  Values should be sorted and can be repeated.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SegmentSum'.
        /// </param>
        /// <returns>
        ///    Has same shape as data, except for dimension 0 which
        ///    has size <c>k</c>, the number of segments.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Read
        ///    [the section on segmentation](https://tensorflow.org/api_guides/python/math_ops#Segmentation)
        ///    for an explanation of segments.
        ///    
        ///    Computes a tensor such that
        ///    \\(output_i = \sum_j data_j\\) where sum is over <c>j</c> such
        ///    that <c>segment_ids[j] == i</c>.
        ///    
        ///    If the sum is empty for a given segment ID <c>i</c>, <c>output[i] = 0</c>.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src="https://www.tensorflow.org/images/SegmentSum.png" alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Tensor segment_sum (Tensor data, Tensor segment_ids, string name = "SegmentSum")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            dict["segment_ids"] = segment_ids;
            var op = _op_def_lib._apply_op_helper("SegmentSum", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Selects elements from <c>x</c> or <c>y</c>, depending on <c>condition</c>.
        /// </summary>
        /// <param name="condition">
        /// </param>
        /// <param name="t">
        ///    = A <c>Tensor</c> which may have the same shape as <c>condition</c>.
        ///    If <c>condition</c> is rank 1, <c>x</c> may have higher rank,
        ///    but its first dimension must match the size of <c>condition</c>.
        /// </param>
        /// <param name="e">
        ///    = A <c>Tensor</c> with the same type and shape as <c>x</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Select'.
        /// </param>
        /// <returns>
        ///    = A <c>Tensor</c> with the same type and shape as <c>x</c> and <c>y</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The <c>x</c>, and <c>y</c> tensors must all have the same shape, and the
        ///    output will also have that shape.
        ///    
        ///    The <c>condition</c> tensor must be a scalar if <c>x</c> and <c>y</c> are scalars.
        ///    If <c>x</c> and <c>y</c> are vectors or higher rank, then <c>condition</c> must be either a
        ///    scalar, a vector with size matching the first dimension of <c>x</c>, or must have
        ///    the same shape as <c>x</c>.
        ///    
        ///    The <c>condition</c> tensor acts as a mask that chooses, based on the value at each
        ///    element, whether the corresponding element / row in the output should be
        ///    taken from <c>x</c> (if true) or <c>y</c> (if false).
        ///    
        ///    If <c>condition</c> is a vector and <c>x</c> and <c>y</c> are higher rank matrices, then
        ///    it chooses which row (outer dimension) to copy from <c>x</c> and <c>y</c>.
        ///    If <c>condition</c> has the same shape as <c>x</c> and <c>y</c>, then it chooses which
        ///    element to copy from <c>x</c> and <c>y</c>.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # 'condition' tensor is [[True,  False]
        ///    #                        [False, True]]
        ///    # 't' is [[1, 2],
        ///    #         [3, 4]]
        ///    # 'e' is [[5, 6],
        ///    #         [7, 8]]
        ///    select(condition, t, e)  # =&amp;gt; [[1, 6], [7, 4]]
        ///    
        ///    
        ///    # 'condition' tensor is [True, False]
        ///    # 't' is [[1, 2],
        ///    #         [3, 4]]
        ///    # 'e' is [[5, 6],
        ///    #         [7, 8]]
        ///    select(condition, t, e) ==&amp;gt; [[1, 2],
        ///    [7, 8]]
        ///    
        ///   </code>
        /// </remarks>
        public static Tensor select (Tensor condition, Tensor t, Tensor e, string name = "Select")
        {
            var dict = new Dictionary<string, object>();
            dict["condition"] = condition;
            dict["t"] = t;
            dict["e"] = e;
            var op = _op_def_lib._apply_op_helper("Select", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the Eigen Decomposition of a batch of square self-adjoint matrices.
        /// </summary>
        /// <param name="input">
        ///    Shape is <c>[..., M, M]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SelfAdjointEig'.
        /// </param>
        /// <returns>
        ///    Shape is <c>[..., M+1, M]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The input is a tensor of shape <c>[..., M, M]</c> whose inner-most 2 dimensions
        ///    form square matrices, with the same constraints as the single matrix
        ///    SelfAdjointEig.
        ///    
        ///    The result is a [..., M+1, M] matrix with [..., 0,:] containing the
        ///    eigenvalues, and subsequent [...,1:, :] containing the eigenvectors. The eigenvalues
        ///    are sorted in non-decreasing order.
        /// </remarks>
        public static Tensor self_adjoint_eig (Tensor input, string name = "SelfAdjointEig")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("SelfAdjointEig", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the eigen decomposition of one or more square self-adjoint matrices.
        /// </summary>
        /// <param name="input">
        ///    <c>Tensor</c> input of shape <c>[N, N]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SelfAdjointEigV2'.
        /// </param>
        /// <param name="compute_v">
        ///    If <c>True</c> then eigenvectors will be computed and returned in <c>v</c>.
        ///    Otherwise, only the eigenvalues will be computed.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    e : Eigenvalues. Shape is <c>[N]</c>.
        ///    v : Eigenvectors. Shape is <c>[N, N]</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Computes the eigenvalues and (optionally) eigenvectors of each inner matrix in
        ///    <c>input</c> such that <c>input[..., :, :] = v[..., :, :] * diag(e[..., :])</c>. The eigenvalues
        ///    are sorted in non-decreasing order.
        ///    
        ///   <code>
        ///    # a is a tensor.
        ///    # e is a tensor of eigenvalues.
        ///    # v is a tensor of eigenvectors.
        ///    e, v = self_adjoint_eig(a)
        ///    e = self_adjoint_eig(a, compute_v=False)
        ///   </code>
        /// </remarks>
        public static (Tensor e, Tensor v) self_adjoint_eig_v2 (Tensor input, bool? compute_v = null, string name = "SelfAdjointEigV2")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (compute_v.HasValue)
                dict["compute_v"] = compute_v.Value;
            var op = _op_def_lib._apply_op_helper("SelfAdjointEigV2", name: name, keywords: dict);
            int _idx = 0;
            var e = op.outputs[_idx++];
            var v = op.outputs[_idx++];
            return (e, v);
        }

        /// <summary>
        ///    Computes scaled exponential linear: <c>scale * alpha * (exp(features) - 1)</c>
        /// </summary>
        /// <param name="features">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Selu'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    if &amp;lt; 0, <c>scale * features</c> otherwise.
        ///    
        ///    To be used together with
        ///    <c>initializer = tf.variance_scaling_initializer(factor=1.0, mode='FAN_IN')</c>.
        ///    For correct dropout, use <c>tf.contrib.nn.alpha_dropout</c>.
        ///    
        ///    See [Self-Normalizing Neural Networks](https://arxiv.org/abs/1706.02515)
        /// </remarks>
        public static Tensor selu (Tensor features, string name = "Selu")
        {
            var dict = new Dictionary<string, object>();
            dict["features"] = features;
            var op = _op_def_lib._apply_op_helper("Selu", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes gradients for the scaled exponential linear (Selu) operation.
        /// </summary>
        /// <param name="gradients">
        ///    The backpropagated gradients to the corresponding Selu operation.
        /// </param>
        /// <param name="outputs">
        ///    The outputs of the corresponding Selu operation.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SeluGrad'.
        /// </param>
        /// <returns>
        ///    The gradients: <c>gradients * (outputs + scale * alpha)</c>
        ///    if outputs &amp;lt; 0, <c>scale * gradients</c> otherwise.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor selu_grad (Tensor gradients, Tensor outputs, string name = "SeluGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["gradients"] = gradients;
            dict["outputs"] = outputs;
            var op = _op_def_lib._apply_op_helper("SeluGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Converts the given <c>resource_handle</c> representing an iterator to a variant tensor.
        /// </summary>
        /// <param name="resource_handle">
        ///    A handle to an iterator resource.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SerializeIterator'.
        /// </param>
        /// <returns>
        ///    A variant tensor storing the state of the iterator contained in the
        ///    resource.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor serialize_iterator (Tensor resource_handle, string name = "SerializeIterator")
        {
            var dict = new Dictionary<string, object>();
            dict["resource_handle"] = resource_handle;
            var op = _op_def_lib._apply_op_helper("SerializeIterator", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Serialize an <c>N</c>-minibatch <c>SparseTensor</c> into an <c>[N, 3]</c> <c>Tensor</c> object.
        /// </summary>
        /// <param name="sparse_indices">
        ///    2-D.  The <c>indices</c> of the minibatch <c>SparseTensor</c>.
        /// </param>
        /// <param name="sparse_values">
        ///    1-D.  The <c>values</c> of the minibatch <c>SparseTensor</c>.
        /// </param>
        /// <param name="sparse_shape">
        ///    1-D.  The <c>shape</c> of the minibatch <c>SparseTensor</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SerializeManySparse'.
        /// </param>
        /// <param name="out_type">
        ///    The <c>dtype</c> to use for serialization; the supported types are <c>string</c>
        ///    (default) and <c>variant</c>.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The <c>SparseTensor</c> must have rank <c>R</c> greater than 1, and the first dimension
        ///    is treated as the minibatch dimension.  Elements of the <c>SparseTensor</c>
        ///    must be sorted in increasing order of this first dimension.  The serialized
        ///    <c>SparseTensor</c> objects going into each row of <c>serialized_sparse</c> will have
        ///    rank <c>R-1</c>.
        ///    
        ///    The minibatch size <c>N</c> is extracted from <c>sparse_shape[0]</c>.
        /// </remarks>
        public static Tensor serialize_many_sparse (Tensor sparse_indices, Tensor sparse_values, Tensor sparse_shape, TF_DataType? out_type = null, string name = "SerializeManySparse")
        {
            var dict = new Dictionary<string, object>();
            dict["sparse_indices"] = sparse_indices;
            dict["sparse_values"] = sparse_values;
            dict["sparse_shape"] = sparse_shape;
            if (out_type.HasValue)
                dict["out_type"] = out_type.Value;
            var op = _op_def_lib._apply_op_helper("SerializeManySparse", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Serialize a <c>SparseTensor</c> into a <c>[3]</c> <c>Tensor</c> object.
        /// </summary>
        /// <param name="sparse_indices">
        ///    2-D.  The <c>indices</c> of the <c>SparseTensor</c>.
        /// </param>
        /// <param name="sparse_values">
        ///    1-D.  The <c>values</c> of the <c>SparseTensor</c>.
        /// </param>
        /// <param name="sparse_shape">
        ///    1-D.  The <c>shape</c> of the <c>SparseTensor</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SerializeSparse'.
        /// </param>
        /// <param name="out_type">
        ///    The <c>dtype</c> to use for serialization; the supported types are <c>string</c>
        ///    (default) and <c>variant</c>.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor serialize_sparse (Tensor sparse_indices, Tensor sparse_values, Tensor sparse_shape, TF_DataType? out_type = null, string name = "SerializeSparse")
        {
            var dict = new Dictionary<string, object>();
            dict["sparse_indices"] = sparse_indices;
            dict["sparse_values"] = sparse_values;
            dict["sparse_shape"] = sparse_shape;
            if (out_type.HasValue)
                dict["out_type"] = out_type.Value;
            var op = _op_def_lib._apply_op_helper("SerializeSparse", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Transforms a Tensor into a serialized TensorProto proto.
        /// </summary>
        /// <param name="tensor">
        ///    A Tensor of type <c>T</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SerializeTensor'.
        /// </param>
        /// <returns>
        ///    A serialized TensorProto proto of the input tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor serialize_tensor (Tensor tensor, string name = "SerializeTensor")
        {
            var dict = new Dictionary<string, object>();
            dict["tensor"] = tensor;
            var op = _op_def_lib._apply_op_helper("SerializeTensor", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Number of unique elements along last dimension of input <c>set</c>.
        /// </summary>
        /// <param name="set_indices">
        ///    2D <c>Tensor</c>, indices of a <c>SparseTensor</c>.
        /// </param>
        /// <param name="set_values">
        ///    1D <c>Tensor</c>, values of a <c>SparseTensor</c>.
        /// </param>
        /// <param name="set_shape">
        ///    1D <c>Tensor</c>, shape of a <c>SparseTensor</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SetSize'.
        /// </param>
        /// <param name="validate_indices">
        /// </param>
        /// <returns>
        ///    For <c>set</c> ranked <c>n</c>, this is a <c>Tensor</c> with rank <c>n-1</c>, and the same 1st
        ///    <c>n-1</c> dimensions as <c>set</c>. Each value is the number of unique elements in
        ///    the corresponding <c>[0...n-1]</c> dimension of <c>set</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Input <c>set</c> is a <c>SparseTensor</c> represented by <c>set_indices</c>, <c>set_values</c>,
        ///    and <c>set_shape</c>. The last dimension contains values in a set, duplicates are
        ///    allowed but ignored.
        ///    
        ///    If <c>validate_indices</c> is <c>True</c>, this op validates the order and range of <c>set</c>
        ///    indices.
        /// </remarks>
        public static Tensor set_size (Tensor set_indices, Tensor set_values, Tensor set_shape, bool? validate_indices = null, string name = "SetSize")
        {
            var dict = new Dictionary<string, object>();
            dict["set_indices"] = set_indices;
            dict["set_values"] = set_values;
            dict["set_shape"] = set_shape;
            if (validate_indices.HasValue)
                dict["validate_indices"] = validate_indices.Value;
            var op = _op_def_lib._apply_op_helper("SetSize", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the shape of a tensor.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Shape'.
        /// </param>
        /// <param name="out_type">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation returns a 1-D integer tensor representing the shape of <c>input</c>.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # 't' is [[[1, 1, 1], [2, 2, 2]], [[3, 3, 3], [4, 4, 4]]]
        ///    shape(t) ==&amp;gt; [2, 2, 3]
        ///   </code>
        /// </remarks>
        public static Tensor shape (Tensor input, TF_DataType? out_type = null, string name = "Shape")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (out_type.HasValue)
                dict["out_type"] = out_type.Value;
            var op = _op_def_lib._apply_op_helper("Shape", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns shape of tensors.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ShapeN'.
        /// </param>
        /// <param name="out_type">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation returns N 1-D integer tensors representing shape of <c>input[i]s</c>.
        /// </remarks>
        public static Tensor[] shape_n (Tensor[] input, TF_DataType? out_type = null, string name = "ShapeN")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (out_type.HasValue)
                dict["out_type"] = out_type.Value;
            var op = _op_def_lib._apply_op_helper("ShapeN", name: name, keywords: dict);
            int _idx = 0;
            var output = Enumerable.Range(0, op.OutputListLength("output")).Select(_ => op.outputs[_idx++]).ToArray();
            return (output);
        }

        /// <summary>
        ///    Generate a sharded filename. The filename is printf formatted as
        /// </summary>
        /// <param name="basename">
        /// </param>
        /// <param name="shard">
        /// </param>
        /// <param name="num_shards">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ShardedFilename'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    %s-%05d-of-%05d, basename, shard, num_shards.
        /// </remarks>
        public static Tensor sharded_filename (Tensor basename, Tensor shard, Tensor num_shards, string name = "ShardedFilename")
        {
            var dict = new Dictionary<string, object>();
            dict["basename"] = basename;
            dict["shard"] = shard;
            dict["num_shards"] = num_shards;
            var op = _op_def_lib._apply_op_helper("ShardedFilename", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Generate a glob pattern matching all sharded file names.
        /// </summary>
        /// <param name="basename">
        /// </param>
        /// <param name="num_shards">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ShardedFilespec'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor sharded_filespec (Tensor basename, Tensor num_shards, string name = "ShardedFilespec")
        {
            var dict = new Dictionary<string, object>();
            dict["basename"] = basename;
            dict["num_shards"] = num_shards;
            var op = _op_def_lib._apply_op_helper("ShardedFilespec", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a dataset that shuffles and repeats elements from <c>input_dataset</c>
        /// </summary>
        /// <param name="input_dataset">
        /// </param>
        /// <param name="buffer_size">
        ///    The number of output elements to buffer in an iterator over
        ///    this dataset. Compare with the <c>min_after_dequeue</c> attr when creating a
        ///    <c>RandomShuffleQueue</c>.
        /// </param>
        /// <param name="seed">
        ///    A scalar seed for the random number generator. If either <c>seed</c> or
        ///    <c>seed2</c> is set to be non-zero, the random number generator is seeded
        ///    by the given seed.  Otherwise, a random seed is used.
        /// </param>
        /// <param name="seed2">
        ///    A second scalar seed to avoid seed collision.
        /// </param>
        /// <param name="count">
        ///    A scalar representing the number of times the underlying dataset
        ///    should be repeated. The default is <c>-1</c>, which results in infinite repetition.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ShuffleAndRepeatDataset'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    pseudorandomly.
        /// </remarks>
        public static Tensor shuffle_and_repeat_dataset (Tensor input_dataset, Tensor buffer_size, Tensor seed, Tensor seed2, Tensor count, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "ShuffleAndRepeatDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["buffer_size"] = buffer_size;
            dict["seed"] = seed;
            dict["seed2"] = seed2;
            dict["count"] = count;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("ShuffleAndRepeatDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a dataset that shuffles elements from <c>input_dataset</c> pseudorandomly.
        /// </summary>
        /// <param name="input_dataset">
        /// </param>
        /// <param name="buffer_size">
        ///    The number of output elements to buffer in an iterator over
        ///    this dataset. Compare with the <c>min_after_dequeue</c> attr when creating a
        ///    <c>RandomShuffleQueue</c>.
        /// </param>
        /// <param name="seed">
        ///    A scalar seed for the random number generator. If either <c>seed</c> or
        ///    <c>seed2</c> is set to be non-zero, the random number generator is seeded
        ///    by the given seed.  Otherwise, a random seed is used.
        /// </param>
        /// <param name="seed2">
        ///    A second scalar seed to avoid seed collision.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ShuffleDataset'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <param name="reshuffle_each_iteration">
        ///    If true, each iterator over this dataset will be given
        ///    a different pseudorandomly generated seed, based on a sequence seeded by the
        ///    <c>seed</c> and <c>seed2</c> inputs. If false, each iterator will be given the same
        ///    seed, and repeated iteration over this dataset will yield the exact same
        ///    sequence of results.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor shuffle_dataset (Tensor input_dataset, Tensor buffer_size, Tensor seed, Tensor seed2, TF_DataType[] output_types, TensorShape[] output_shapes, bool? reshuffle_each_iteration = null, string name = "ShuffleDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["buffer_size"] = buffer_size;
            dict["seed"] = seed;
            dict["seed2"] = seed2;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            if (reshuffle_each_iteration.HasValue)
                dict["reshuffle_each_iteration"] = reshuffle_each_iteration.Value;
            var op = _op_def_lib._apply_op_helper("ShuffleDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    An op that shuts down a running distributed TPU system. The Op returns
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ShutdownDistributedTPU'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    an error if no system is running.
        /// </remarks>
        public static Operation shutdown_distributed_t_p_u (string name = "ShutdownDistributedTPU")
        {
            var dict = new Dictionary<string, object>();
            var op = _op_def_lib._apply_op_helper("ShutdownDistributedTPU", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Computes sigmoid of <c>x</c> element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Sigmoid'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Specifically, <c>y = 1 / (1 + exp(-x))</c>.
        /// </remarks>
        public static Tensor sigmoid (Tensor x, string name = "Sigmoid")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Sigmoid", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradient of the sigmoid of <c>x</c> wrt its input.
        /// </summary>
        /// <param name="y">
        /// </param>
        /// <param name="dy">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SigmoidGrad'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Specifically, <c>grad = dy * y * (1 - y)</c>, where <c>y = sigmoid(x)</c>, and
        ///    <c>dy</c> is the corresponding input gradient.
        /// </remarks>
        public static Tensor sigmoid_grad (Tensor y, Tensor dy, string name = "SigmoidGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["y"] = y;
            dict["dy"] = dy;
            var op = _op_def_lib._apply_op_helper("SigmoidGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns an element-wise indication of the sign of a number.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Sign'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    <c>y = sign(x) = -1</c> if <c>x &amp;lt; 0</c>; 0 if <c>x == 0</c>; 1 if <c>x &amp;gt; 0</c>.
        ///    
        ///    For complex numbers, <c>y = sign(x) = x / |x|</c> if <c>x != 0</c>, otherwise <c>y = 0</c>.
        /// </remarks>
        public static Tensor sign (Tensor x, string name = "Sign")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Sign", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes sin of x element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Sin'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor sin (Tensor x, string name = "Sin")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Sin", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes hyperbolic sine of x element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Sinh'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor sinh (Tensor x, string name = "Sinh")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Sinh", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A placeholder for input pipeline graph optimizations.
        /// </summary>
        /// <param name="input_dataset">
        ///    A variant tensor representing the input dataset.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SinkDataset'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    A placeholder for input pipeline graph optimizations.
        /// </remarks>
        public static Tensor sink_dataset (Tensor input_dataset, string name = "SinkDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            var op = _op_def_lib._apply_op_helper("SinkDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the size of a tensor.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Size'.
        /// </param>
        /// <param name="out_type">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation returns an integer representing the number of elements in
        ///    <c>input</c>.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # 't' is [[[1, 1,, 1], [2, 2, 2]], [[3, 3, 3], [4, 4, 4]]]]
        ///    size(t) ==&amp;gt; 12
        ///   </code>
        /// </remarks>
        public static Tensor size (Tensor input, TF_DataType? out_type = null, string name = "Size")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (out_type.HasValue)
                dict["out_type"] = out_type.Value;
            var op = _op_def_lib._apply_op_helper("Size", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a dataset that skips <c>count</c> elements from the <c>input_dataset</c>.
        /// </summary>
        /// <param name="input_dataset">
        /// </param>
        /// <param name="count">
        ///    A scalar representing the number of elements from the <c>input_dataset</c>
        ///    that should be skipped.  If count is -1, skips everything.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SkipDataset'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor skip_dataset (Tensor input_dataset, Tensor count, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "SkipDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["count"] = count;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("SkipDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Parses a text file and creates a batch of examples.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Skipgram'.
        /// </param>
        /// <param name="filename">
        ///    Optional argument
        ///    The corpus's text file name.
        /// </param>
        /// <param name="batch_size">
        ///    Optional argument
        ///    The size of produced batch.
        /// </param>
        /// <param name="window_size">
        ///    The number of words to predict to the left and right of the target.
        /// </param>
        /// <param name="min_count">
        ///    The minimum number of word occurrences for it to be included in the
        ///    vocabulary.
        /// </param>
        /// <param name="subsample">
        ///    Threshold for word occurrence. Words that appear with higher
        ///    frequency will be randomly down-sampled. Set to 0 to disable.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    vocab_word : A vector of words in the corpus.
        ///    vocab_freq : Frequencies of words. Sorted in the non-ascending order.
        ///    words_per_epoch : Number of words per epoch in the data file.
        ///    current_epoch : The current epoch number.
        ///    total_words_processed : The total number of words processed so far.
        ///    examples : A vector of word ids.
        ///    labels : A vector of word ids.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor vocab_word, Tensor vocab_freq, Tensor words_per_epoch, Tensor current_epoch, Tensor total_words_processed, Tensor examples, Tensor labels) skipgram (string filename, int batch_size, int? window_size = null, int? min_count = null, float? subsample = null, string name = "Skipgram")
        {
            var dict = new Dictionary<string, object>();
            dict["filename"] = filename;
            dict["batch_size"] = batch_size;
            if (window_size.HasValue)
                dict["window_size"] = window_size.Value;
            if (min_count.HasValue)
                dict["min_count"] = min_count.Value;
            if (subsample.HasValue)
                dict["subsample"] = subsample.Value;
            var op = _op_def_lib._apply_op_helper("Skipgram", name: name, keywords: dict);
            int _idx = 0;
            var vocab_word = op.outputs[_idx++];
            var vocab_freq = op.outputs[_idx++];
            var words_per_epoch = op.outputs[_idx++];
            var current_epoch = op.outputs[_idx++];
            var total_words_processed = op.outputs[_idx++];
            var examples = op.outputs[_idx++];
            var labels = op.outputs[_idx++];
            return (vocab_word, vocab_freq, words_per_epoch, current_epoch, total_words_processed, examples, labels);
        }

        /// <summary>
        ///    Return a slice from 'input'.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="begin">
        ///    begin[i] specifies the offset into the 'i'th dimension of
        ///    'input' to slice from.
        /// </param>
        /// <param name="size">
        ///    size[i] specifies the number of elements of the 'i'th dimension
        ///    of 'input' to slice. If size[i] is -1, all remaining elements in dimension
        ///    i are included in the slice (i.e. this is equivalent to setting
        ///    size[i] = input.dim_size(i) - begin[i]).
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Slice'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The output tensor is a tensor with dimensions described by 'size'
        ///    whose values are extracted from 'input' starting at the offsets in
        ///    'begin'.
        ///    
        ///    *Requirements*:
        ///    0 &amp;lt;= begin[i] &amp;lt;= begin[i] + size[i] &amp;lt;= Di  for i in [0, n)
        /// </remarks>
        public static Tensor slice (Tensor input, Tensor begin, Tensor size, string name = "Slice")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["begin"] = begin;
            dict["size"] = size;
            var op = _op_def_lib._apply_op_helper("Slice", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a dataset that passes a sliding window over <c>input_dataset</c>.
        /// </summary>
        /// <param name="input_dataset">
        /// </param>
        /// <param name="window_size">
        ///    A scalar representing the number of elements in the
        ///    sliding window.
        /// </param>
        /// <param name="window_shift">
        ///    A scalar representing the steps moving the sliding window
        ///    forward in one iteration. It must be positive.
        /// </param>
        /// <param name="window_stride">
        ///    A scalar representing the stride of the input elements of the sliding window.
        ///    It must be positive.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SlideDataset'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor slide_dataset (Tensor input_dataset, Tensor window_size, Tensor window_shift, Tensor window_stride, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "SlideDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["window_size"] = window_size;
            dict["window_shift"] = window_shift;
            dict["window_stride"] = window_stride;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("SlideDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns a copy of the input tensor.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Snapshot'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor snapshot (Tensor input, string name = "Snapshot")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("Snapshot", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes softmax activations.
        /// </summary>
        /// <param name="logits">
        ///    2-D with shape <c>[batch_size, num_classes]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Softmax'.
        /// </param>
        /// <returns>
        ///    Same shape as <c>logits</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    For each batch <c>i</c> and class <c>j</c> we have
        ///    
        ///    $$softmax[i, j] = exp(logits[i, j]) / sum_j(exp(logits[i, j]))$$
        /// </remarks>
        public static Tensor softmax (Tensor logits, string name = "Softmax")
        {
            var dict = new Dictionary<string, object>();
            dict["logits"] = logits;
            var op = _op_def_lib._apply_op_helper("Softmax", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes softmax cross entropy cost and gradients to backpropagate.
        /// </summary>
        /// <param name="features">
        ///    batch_size x num_classes matrix
        /// </param>
        /// <param name="labels">
        ///    batch_size x num_classes matrix
        ///    The caller must ensure that each batch of labels represents a valid
        ///    probability distribution.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SoftmaxCrossEntropyWithLogits'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    loss : Per example loss (batch_size vector).
        ///    backprop : backpropagated gradients (batch_size x num_classes matrix).
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Inputs are the logits, not probabilities.
        /// </remarks>
        public static (Tensor loss, Tensor backprop) softmax_cross_entropy_with_logits (Tensor features, Tensor labels, string name = "SoftmaxCrossEntropyWithLogits")
        {
            var dict = new Dictionary<string, object>();
            dict["features"] = features;
            dict["labels"] = labels;
            var op = _op_def_lib._apply_op_helper("SoftmaxCrossEntropyWithLogits", name: name, keywords: dict);
            int _idx = 0;
            var loss = op.outputs[_idx++];
            var backprop = op.outputs[_idx++];
            return (loss, backprop);
        }

        /// <summary>
        ///    Computes softplus: <c>log(exp(features) + 1)</c>.
        /// </summary>
        /// <param name="features">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Softplus'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor softplus (Tensor features, string name = "Softplus")
        {
            var dict = new Dictionary<string, object>();
            dict["features"] = features;
            var op = _op_def_lib._apply_op_helper("Softplus", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes softplus gradients for a softplus operation.
        /// </summary>
        /// <param name="gradients">
        ///    The backpropagated gradients to the corresponding softplus operation.
        /// </param>
        /// <param name="features">
        ///    The features passed as input to the corresponding softplus operation.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SoftplusGrad'.
        /// </param>
        /// <returns>
        ///    The gradients: <c>gradients / (1 + exp(-features))</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor softplus_grad (Tensor gradients, Tensor features, string name = "SoftplusGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["gradients"] = gradients;
            dict["features"] = features;
            var op = _op_def_lib._apply_op_helper("SoftplusGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes softsign: <c>features / (abs(features) + 1)</c>.
        /// </summary>
        /// <param name="features">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Softsign'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor softsign (Tensor features, string name = "Softsign")
        {
            var dict = new Dictionary<string, object>();
            dict["features"] = features;
            var op = _op_def_lib._apply_op_helper("Softsign", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes softsign gradients for a softsign operation.
        /// </summary>
        /// <param name="gradients">
        ///    The backpropagated gradients to the corresponding softsign operation.
        /// </param>
        /// <param name="features">
        ///    The features passed as input to the corresponding softsign operation.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SoftsignGrad'.
        /// </param>
        /// <returns>
        ///    The gradients: <c>gradients / (1 + abs(features)) ** 2</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor softsign_grad (Tensor gradients, Tensor features, string name = "SoftsignGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["gradients"] = gradients;
            dict["features"] = features;
            var op = _op_def_lib._apply_op_helper("SoftsignGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    SpaceToBatch for 4-D tensors of type T.
        /// </summary>
        /// <param name="input">
        ///    4-D with shape <c>[batch, height, width, depth]</c>.
        /// </param>
        /// <param name="paddings">
        ///    2-D tensor of non-negative integers with shape <c>[2, 2]</c>. It specifies
        ///    the padding of the input with zeros across the spatial dimensions as follows:
        ///    
        ///    paddings = [[pad_top, pad_bottom], [pad_left, pad_right]]
        ///    
        ///    The effective spatial dimensions of the zero-padded input tensor will be:
        ///    
        ///    height_pad = pad_top + height + pad_bottom
        ///    width_pad = pad_left + width + pad_right
        ///    
        ///    The attr <c>block_size</c> must be greater than one. It indicates the block size.
        ///    
        ///    * Non-overlapping blocks of size <c>block_size x block size</c> in the height and
        ///    width dimensions are rearranged into the batch dimension at each location.
        ///    * The batch of the output tensor is <c>batch * block_size * block_size</c>.
        ///    * Both height_pad and width_pad must be divisible by block_size.
        ///    
        ///    The shape of the output will be:
        ///    
        ///    [batch*block_size*block_size, height_pad/block_size, width_pad/block_size,
        ///    depth]
        ///    
        ///    Some examples:
        ///    
        ///    (1) For the following input of shape <c>[1, 2, 2, 1]</c> and block_size of 2:
        ///    
        ///   <code>
        ///    x = [[[[1], [2]], [[3], [4]]]]
        ///   </code>
        ///    
        ///    The output tensor has shape <c>[4, 1, 1, 1]</c> and value:
        ///    
        ///   <code>
        ///    [[[[1]]], [[[2]]], [[[3]]], [[[4]]]]
        ///   </code>
        ///    
        ///    (2) For the following input of shape <c>[1, 2, 2, 3]</c> and block_size of 2:
        ///    
        ///   <code>
        ///    x = [[[[1, 2, 3], [4, 5, 6]],
        ///    [[7, 8, 9], [10, 11, 12]]]]
        ///   </code>
        ///    
        ///    The output tensor has shape <c>[4, 1, 1, 3]</c> and value:
        ///    
        ///   <code>
        ///    [[[1, 2, 3]], [[4, 5, 6]], [[7, 8, 9]], [[10, 11, 12]]]
        ///   </code>
        ///    
        ///    (3) For the following input of shape <c>[1, 4, 4, 1]</c> and block_size of 2:
        ///    
        ///   <code>
        ///    x = [[[[1],   [2],  [3],  [4]],
        ///    [[5],   [6],  [7],  [8]],
        ///    [[9],  [10], [11],  [12]],
        ///    [[13], [14], [15],  [16]]]]
        ///   </code>
        ///    
        ///    The output tensor has shape <c>[4, 2, 2, 1]</c> and value:
        ///    
        ///   <code>
        ///    x = [[[[1], [3]], [[9], [11]]],
        ///    [[[2], [4]], [[10], [12]]],
        ///    [[[5], [7]], [[13], [15]]],
        ///    [[[6], [8]], [[14], [16]]]]
        ///   </code>
        ///    
        ///    (4) For the following input of shape <c>[2, 2, 4, 1]</c> and block_size of 2:
        ///    
        ///   <code>
        ///    x = [[[[1],   [2],  [3],  [4]],
        ///    [[5],   [6],  [7],  [8]]],
        ///    [[[9],  [10], [11],  [12]],
        ///    [[13], [14], [15],  [16]]]]
        ///   </code>
        ///    
        ///    The output tensor has shape <c>[8, 1, 2, 1]</c> and value:
        ///    
        ///   <code>
        ///    x = [[[[1], [3]]], [[[9], [11]]], [[[2], [4]]], [[[10], [12]]],
        ///    [[[5], [7]]], [[[13], [15]]], [[[6], [8]]], [[[14], [16]]]]
        ///   </code>
        ///    
        ///    Among others, this operation is useful for reducing atrous convolution into
        ///    regular convolution.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SpaceToBatch'.
        /// </param>
        /// <param name="block_size">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This is a legacy version of the more general SpaceToBatchND.
        ///    
        ///    Zero-pads and then rearranges (permutes) blocks of spatial data into batch.
        ///    More specifically, this op outputs a copy of the input tensor where values from
        ///    the <c>height</c> and <c>width</c> dimensions are moved to the <c>batch</c> dimension. After
        ///    the zero-padding, both <c>height</c> and <c>width</c> of the input must be divisible by the
        ///    block size.
        /// </remarks>
        public static Tensor space_to_batch (Tensor input, Tensor paddings, int block_size, string name = "SpaceToBatch")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["paddings"] = paddings;
            dict["block_size"] = block_size;
            var op = _op_def_lib._apply_op_helper("SpaceToBatch", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    SpaceToBatch for N-D tensors of type T.
        /// </summary>
        /// <param name="input">
        ///    N-D with shape <c>input_shape = [batch] + spatial_shape + remaining_shape</c>,
        ///    where spatial_shape has <c>M</c> dimensions.
        /// </param>
        /// <param name="block_shape">
        ///    1-D with shape <c>[M]</c>, all values must be &amp;gt;= 1.
        /// </param>
        /// <param name="paddings">
        ///    2-D with shape <c>[M, 2]</c>, all values must be &amp;gt;= 0.
        ///    <c>paddings[i] = [pad_start, pad_end]</c> specifies the padding for input dimension
        ///    <c>i + 1</c>, which corresponds to spatial dimension <c>i</c>.  It is required that
        ///    <c>block_shape[i]</c> divides <c>input_shape[i + 1] + pad_start + pad_end</c>.
        ///    
        ///    This operation is equivalent to the following steps:
        ///    
        ///    1. Zero-pad the start and end of dimensions <c>[1, ..., M]</c> of the
        ///    input according to <c>paddings</c> to produce <c>padded</c> of shape <c>padded_shape</c>.
        ///    
        ///    2. Reshape <c>padded</c> to <c>reshaped_padded</c> of shape:
        ///    
        ///    [batch] +
        ///    [padded_shape[1] / block_shape[0],
        ///    block_shape[0],
        ///    ...,
        ///    padded_shape[M] / block_shape[M-1],
        ///    block_shape[M-1]] +
        ///    remaining_shape
        ///    
        ///    3. Permute dimensions of <c>reshaped_padded</c> to produce
        ///    <c>permuted_reshaped_padded</c> of shape:
        ///    
        ///    block_shape +
        ///    [batch] +
        ///    [padded_shape[1] / block_shape[0],
        ///    ...,
        ///    padded_shape[M] / block_shape[M-1]] +
        ///    remaining_shape
        ///    
        ///    4. Reshape <c>permuted_reshaped_padded</c> to flatten <c>block_shape</c> into the batch
        ///    dimension, producing an output tensor of shape:
        ///    
        ///    [batch * prod(block_shape)] +
        ///    [padded_shape[1] / block_shape[0],
        ///    ...,
        ///    padded_shape[M] / block_shape[M-1]] +
        ///    remaining_shape
        ///    
        ///    Some examples:
        ///    
        ///    (1) For the following input of shape <c>[1, 2, 2, 1]</c>, <c>block_shape = [2, 2]</c>, and
        ///    <c>paddings = [[0, 0], [0, 0]]</c>:
        ///    
        ///   <code>
        ///    x = [[[[1], [2]], [[3], [4]]]]
        ///   </code>
        ///    
        ///    The output tensor has shape <c>[4, 1, 1, 1]</c> and value:
        ///    
        ///   <code>
        ///    [[[[1]]], [[[2]]], [[[3]]], [[[4]]]]
        ///   </code>
        ///    
        ///    (2) For the following input of shape <c>[1, 2, 2, 3]</c>, <c>block_shape = [2, 2]</c>, and
        ///    <c>paddings = [[0, 0], [0, 0]]</c>:
        ///    
        ///   <code>
        ///    x = [[[[1, 2, 3], [4, 5, 6]],
        ///    [[7, 8, 9], [10, 11, 12]]]]
        ///   </code>
        ///    
        ///    The output tensor has shape <c>[4, 1, 1, 3]</c> and value:
        ///    
        ///   <code>
        ///    [[[1, 2, 3]], [[4, 5, 6]], [[7, 8, 9]], [[10, 11, 12]]]
        ///   </code>
        ///    
        ///    (3) For the following input of shape <c>[1, 4, 4, 1]</c>, <c>block_shape = [2, 2]</c>, and
        ///    <c>paddings = [[0, 0], [0, 0]]</c>:
        ///    
        ///   <code>
        ///    x = [[[[1],   [2],  [3],  [4]],
        ///    [[5],   [6],  [7],  [8]],
        ///    [[9],  [10], [11],  [12]],
        ///    [[13], [14], [15],  [16]]]]
        ///   </code>
        ///    
        ///    The output tensor has shape <c>[4, 2, 2, 1]</c> and value:
        ///    
        ///   <code>
        ///    x = [[[[1], [3]], [[9], [11]]],
        ///    [[[2], [4]], [[10], [12]]],
        ///    [[[5], [7]], [[13], [15]]],
        ///    [[[6], [8]], [[14], [16]]]]
        ///   </code>
        ///    
        ///    (4) For the following input of shape <c>[2, 2, 4, 1]</c>, block_shape = <c>[2, 2]</c>, and
        ///    paddings = <c>[[0, 0], [2, 0]]</c>:
        ///    
        ///   <code>
        ///    x = [[[[1],   [2],  [3],  [4]],
        ///    [[5],   [6],  [7],  [8]]],
        ///    [[[9],  [10], [11],  [12]],
        ///    [[13], [14], [15],  [16]]]]
        ///   </code>
        ///    
        ///    The output tensor has shape <c>[8, 1, 3, 1]</c> and value:
        ///    
        ///   <code>
        ///    x = [[[[0], [1], [3]]], [[[0], [9], [11]]],
        ///    [[[0], [2], [4]]], [[[0], [10], [12]]],
        ///    [[[0], [5], [7]]], [[[0], [13], [15]]],
        ///    [[[0], [6], [8]]], [[[0], [14], [16]]]]
        ///   </code>
        ///    
        ///    Among others, this operation is useful for reducing atrous convolution into
        ///    regular convolution.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SpaceToBatchND'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation divides "spatial" dimensions <c>[1, ..., M]</c> of the input into a
        ///    grid of blocks of shape <c>block_shape</c>, and interleaves these blocks with the
        ///    "batch" dimension (0) such that in the output, the spatial dimensions
        ///    <c>[1, ..., M]</c> correspond to the position within the grid, and the batch
        ///    dimension combines both the position within a spatial block and the original
        ///    batch position.  Prior to division into blocks, the spatial dimensions of the
        ///    input are optionally zero padded according to <c>paddings</c>.  See below for a
        ///    precise description.
        /// </remarks>
        public static Tensor space_to_batch_n_d (Tensor input, Tensor block_shape, Tensor paddings, string name = "SpaceToBatchND")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["block_shape"] = block_shape;
            dict["paddings"] = paddings;
            var op = _op_def_lib._apply_op_helper("SpaceToBatchND", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    SpaceToDepth for tensors of type T.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SpaceToDepth'.
        /// </param>
        /// <param name="block_size">
        ///    Optional argument
        ///    The size of the spatial block.
        /// </param>
        /// <param name="data_format">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Rearranges blocks of spatial data, into depth. More specifically,
        ///    this op outputs a copy of the input tensor where values from the <c>height</c>
        ///    and <c>width</c> dimensions are moved to the <c>depth</c> dimension.
        ///    The attr <c>block_size</c> indicates the input block size.
        ///    
        ///    * Non-overlapping blocks of size <c>block_size x block size</c> are rearranged
        ///    into depth at each location.
        ///    * The depth of the output tensor is <c>block_size * block_size * input_depth</c>.
        ///    * The Y, X coordinates within each block of the input become the high order
        ///    component of the output channel index.
        ///    * The input tensor's height and width must be divisible by block_size.
        ///    
        ///    The <c>data_format</c> attr specifies the layout of the input and output tensors
        ///    with the following options:
        ///    "NHWC": <c>[ batch, height, width, channels ]</c>
        ///    "NCHW": <c>[ batch, channels, height, width ]</c>
        ///    "NCHW_VECT_C":
        ///    <c>qint8 [ batch, channels / 4, height, width, 4 ]</c>
        ///    
        ///    It is useful to consider the operation as transforming a 6-D Tensor.
        ///    e.g. for data_format = NHWC,
        ///    Each element in the input tensor can be specified via 6 coordinates,
        ///    ordered by decreasing memory layout significance as:
        ///    n,oY,bY,oX,bX,iC  (where n=batch index, oX, oY means X or Y coordinates
        ///    within the output image, bX, bY means coordinates
        ///    within the input block, iC means input channels).
        ///    The output would be a transpose to the following layout:
        ///    n,oY,oX,bY,bX,iC
        ///    
        ///    This operation is useful for resizing the activations between convolutions
        ///    (but keeping all data), e.g. instead of pooling. It is also useful for training
        ///    purely convolutional models.
        ///    
        ///    For example, given an input of shape <c>[1, 2, 2, 1]</c>, data_format = "NHWC" and
        ///    block_size = 2:
        ///    
        ///   <code>
        ///    x = [[[[1], [2]],
        ///    [[3], [4]]]]
        ///   </code>
        ///    
        ///    This operation will output a tensor of shape <c>[1, 1, 1, 4]</c>:
        ///    
        ///   <code>
        ///    [[[[1, 2, 3, 4]]]]
        ///   </code>
        ///    
        ///    Here, the input has a batch of 1 and each batch element has shape <c>[2, 2, 1]</c>,
        ///    the corresponding output will have a single element (i.e. width and height are
        ///    both 1) and will have a depth of 4 channels (1 * block_size * block_size).
        ///    The output element shape is <c>[1, 1, 4]</c>.
        ///    
        ///    For an input tensor with larger depth, here of shape <c>[1, 2, 2, 3]</c>, e.g.
        ///    
        ///   <code>
        ///    x = [[[[1, 2, 3], [4, 5, 6]],
        ///    [[7, 8, 9], [10, 11, 12]]]]
        ///   </code>
        ///    
        ///    This operation, for block_size of 2, will return the following tensor of shape
        ///    <c>[1, 1, 1, 12]</c>
        ///    
        ///   <code>
        ///    [[[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]]]]
        ///   </code>
        ///    
        ///    Similarly, for the following input of shape <c>[1 4 4 1]</c>, and a block size of 2:
        ///    
        ///   <code>
        ///    x = [[[[1],   [2],  [5],  [6]],
        ///    [[3],   [4],  [7],  [8]],
        ///    [[9],  [10], [13],  [14]],
        ///    [[11], [12], [15],  [16]]]]
        ///   </code>
        ///    
        ///    the operator will return the following tensor of shape <c>[1 2 2 4]</c>:
        ///    
        ///   <code>
        ///    x = [[[[1, 2, 3, 4],
        ///    [5, 6, 7, 8]],
        ///    [[9, 10, 11, 12],
        ///    [13, 14, 15, 16]]]]
        ///   </code>
        /// </remarks>
        public static Tensor space_to_depth (Tensor input, int block_size, string data_format = null, string name = "SpaceToDepth")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["block_size"] = block_size;
            if (data_format != null)
                dict["data_format"] = data_format;
            var op = _op_def_lib._apply_op_helper("SpaceToDepth", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Applies a sparse gradient to a given accumulator.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a accumulator.
        /// </param>
        /// <param name="local_step">
        ///    The local_step value at which the sparse gradient was computed.
        /// </param>
        /// <param name="gradient_indices">
        ///    Indices of the sparse gradient to be accumulated. Must be a
        ///    vector.
        /// </param>
        /// <param name="gradient_values">
        ///    Values are the non-zero slices of the gradient, and must have
        ///    the same first dimension as indices, i.e., the nnz represented by indices and
        ///    values must be consistent.
        /// </param>
        /// <param name="gradient_shape">
        ///    Shape of the sparse gradient to be accumulated.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseAccumulatorApplyGradient'.
        /// </param>
        /// <param name="has_known_shape">
        ///    Optional argument
        ///    Boolean indicating whether gradient_shape is unknown, in which
        ///    case the input is ignored during validation.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    Does not add if local_step is smaller than the accumulator's
        ///    global_step.
        /// </remarks>
        public static Operation sparse_accumulator_apply_gradient (Tensor handle, Tensor local_step, Tensor gradient_indices, Tensor gradient_values, Tensor gradient_shape, bool has_known_shape, string name = "SparseAccumulatorApplyGradient")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["local_step"] = local_step;
            dict["gradient_indices"] = gradient_indices;
            dict["gradient_values"] = gradient_values;
            dict["gradient_shape"] = gradient_shape;
            dict["has_known_shape"] = has_known_shape;
            var op = _op_def_lib._apply_op_helper("SparseAccumulatorApplyGradient", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Extracts the average sparse gradient in a SparseConditionalAccumulator.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a SparseConditionalAccumulator.
        /// </param>
        /// <param name="num_required">
        ///    Number of gradients required before we return an aggregate.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseAccumulatorTakeGradient'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The data type of accumulated gradients. Needs to correspond to the type
        ///    of the accumulator.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    indices : Indices of the average of the accumulated sparse gradients.
        ///    values : Values of the average of the accumulated sparse gradients.
        ///    shape : Shape of the average of the accumulated sparse gradients.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    The op will blocks until sufficient (i.e., more than num_required)
        ///    gradients have been accumulated. If the accumulator has already
        ///    aggregated more than num_required gradients, it will return its
        ///    average of the accumulated gradients.  Also automatically increments
        ///    the recorded global_step in the accumulator by 1, and resets the
        ///    aggregate to 0.
        /// </remarks>
        public static (Tensor indices, Tensor values, Tensor shape) sparse_accumulator_take_gradient (Tensor handle, Tensor num_required, TF_DataType dtype, string name = "SparseAccumulatorTakeGradient")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["num_required"] = num_required;
            dict["dtype"] = dtype;
            var op = _op_def_lib._apply_op_helper("SparseAccumulatorTakeGradient", name: name, keywords: dict);
            int _idx = 0;
            var indices = op.outputs[_idx++];
            var values = op.outputs[_idx++];
            var shape = op.outputs[_idx++];
            return (indices, values, shape);
        }

        /// <summary>
        ///    Adds two <c>SparseTensor</c> objects to produce another <c>SparseTensor</c>.
        /// </summary>
        /// <param name="a_indices">
        ///    2-D.  The <c>indices</c> of the first <c>SparseTensor</c>, size <c>[nnz, ndims]</c> Matrix.
        /// </param>
        /// <param name="a_values">
        ///    1-D.  The <c>values</c> of the first <c>SparseTensor</c>, size <c>[nnz]</c> Vector.
        /// </param>
        /// <param name="a_shape">
        ///    1-D.  The <c>shape</c> of the first <c>SparseTensor</c>, size <c>[ndims]</c> Vector.
        /// </param>
        /// <param name="b_indices">
        ///    2-D.  The <c>indices</c> of the second <c>SparseTensor</c>, size <c>[nnz, ndims]</c> Matrix.
        /// </param>
        /// <param name="b_values">
        ///    1-D.  The <c>values</c> of the second <c>SparseTensor</c>, size <c>[nnz]</c> Vector.
        /// </param>
        /// <param name="b_shape">
        ///    1-D.  The <c>shape</c> of the second <c>SparseTensor</c>, size <c>[ndims]</c> Vector.
        /// </param>
        /// <param name="thresh">
        ///    0-D.  The magnitude threshold that determines if an output value/index
        ///    pair takes space.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseAdd'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    sum_indices :
        ///    sum_values :
        ///    sum_shape :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    The input <c>SparseTensor</c> objects' indices are assumed ordered in standard
        ///    lexicographic order.  If this is not the case, before this step run
        ///    <c>SparseReorder</c> to restore index ordering.
        ///    
        ///    By default, if two values sum to zero at some index, the output <c>SparseTensor</c>
        ///    would still include that particular location in its index, storing a zero in the
        ///    corresponding value slot.  To override this, callers can specify <c>thresh</c>,
        ///    indicating that if the sum has a magnitude strictly smaller than <c>thresh</c>, its
        ///    corresponding value and index would then not be included.  In particular,
        ///    <c>thresh == 0</c> (default) means everything is kept and actual thresholding happens
        ///    only for a positive value.
        ///    
        ///    In the following shapes, <c>nnz</c> is the count after taking <c>thresh</c> into account.
        /// </remarks>
        public static (Tensor sum_indices, Tensor sum_values, Tensor sum_shape) sparse_add (Tensor a_indices, Tensor a_values, Tensor a_shape, Tensor b_indices, Tensor b_values, Tensor b_shape, Tensor thresh, string name = "SparseAdd")
        {
            var dict = new Dictionary<string, object>();
            dict["a_indices"] = a_indices;
            dict["a_values"] = a_values;
            dict["a_shape"] = a_shape;
            dict["b_indices"] = b_indices;
            dict["b_values"] = b_values;
            dict["b_shape"] = b_shape;
            dict["thresh"] = thresh;
            var op = _op_def_lib._apply_op_helper("SparseAdd", name: name, keywords: dict);
            int _idx = 0;
            var sum_indices = op.outputs[_idx++];
            var sum_values = op.outputs[_idx++];
            var sum_shape = op.outputs[_idx++];
            return (sum_indices, sum_values, sum_shape);
        }

        /// <summary>
        ///    The gradient operator for the SparseAdd op.
        /// </summary>
        /// <param name="backprop_val_grad">
        ///    1-D with shape <c>[nnz(sum)]</c>.  The gradient with respect to
        ///    the non-empty values of the sum.
        /// </param>
        /// <param name="a_indices">
        ///    2-D.  The <c>indices</c> of the <c>SparseTensor</c> A, size <c>[nnz(A), ndims]</c>.
        /// </param>
        /// <param name="b_indices">
        ///    2-D.  The <c>indices</c> of the <c>SparseTensor</c> B, size <c>[nnz(B), ndims]</c>.
        /// </param>
        /// <param name="sum_indices">
        ///    2-D.  The <c>indices</c> of the sum <c>SparseTensor</c>, size
        ///    <c>[nnz(sum), ndims]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseAddGrad'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    a_val_grad : 1-D with shape <c>[nnz(A)]</c>. The gradient with respect to the
        ///    non-empty values of A.
        ///    b_val_grad : 1-D with shape <c>[nnz(B)]</c>. The gradient with respect to the
        ///    non-empty values of B.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    The SparseAdd op calculates A + B, where A, B, and the sum are all represented
        ///    as <c>SparseTensor</c> objects.  This op takes in the upstream gradient w.r.t.
        ///    non-empty values of the sum, and outputs the gradients w.r.t. the non-empty
        ///    values of A and B.
        /// </remarks>
        public static (Tensor a_val_grad, Tensor b_val_grad) sparse_add_grad (Tensor backprop_val_grad, Tensor a_indices, Tensor b_indices, Tensor sum_indices, string name = "SparseAddGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["backprop_val_grad"] = backprop_val_grad;
            dict["a_indices"] = a_indices;
            dict["b_indices"] = b_indices;
            dict["sum_indices"] = sum_indices;
            var op = _op_def_lib._apply_op_helper("SparseAddGrad", name: name, keywords: dict);
            int _idx = 0;
            var a_val_grad = op.outputs[_idx++];
            var b_val_grad = op.outputs[_idx++];
            return (a_val_grad, b_val_grad);
        }

        /// <summary>
        ///    var: Should be from a Variable().
        /// </summary>
        /// <param name="var">
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum_update">
        ///    : Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Learning rate. Must be a scalar.
        /// </param>
        /// <param name="rho">
        ///    Decay factor. Must be a scalar.
        /// </param>
        /// <param name="epsilon">
        ///    Constant factor. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="indices">
        ///    A vector of indices into the first dimension of var and accum.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseApplyAdadelta'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, updating of the var and accum tensors will be protected by
        ///    a lock; otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor sparse_apply_adadelta (Tensor var, Tensor accum, Tensor accum_update, Tensor lr, Tensor rho, Tensor epsilon, Tensor grad, Tensor indices, bool? use_locking = null, string name = "SparseApplyAdadelta")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["accum_update"] = accum_update;
            dict["lr"] = lr;
            dict["rho"] = rho;
            dict["epsilon"] = epsilon;
            dict["grad"] = grad;
            dict["indices"] = indices;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("SparseApplyAdadelta", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update relevant entries in '*var' and '*accum' according to the adagrad scheme.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Learning rate. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="indices">
        ///    A vector of indices into the first dimension of var and accum.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseApplyAdagrad'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var and accum tensors will be protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <param name="update_slots">
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    That is for rows we have grad for, we update var and accum as follows:
        ///    $$accum += grad * grad$$
        ///    $$var -= lr * grad * (1 / sqrt(accum))$$
        /// </remarks>
        public static Tensor sparse_apply_adagrad (Tensor var, Tensor accum, Tensor lr, Tensor grad, Tensor indices, bool? use_locking = null, bool? update_slots = null, string name = "SparseApplyAdagrad")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["lr"] = lr;
            dict["grad"] = grad;
            dict["indices"] = indices;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            if (update_slots.HasValue)
                dict["update_slots"] = update_slots.Value;
            var op = _op_def_lib._apply_op_helper("SparseApplyAdagrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update entries in '*var' and '*accum' according to the proximal adagrad scheme.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="gradient_accumulator">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="gradient_squared_accumulator">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="indices">
        ///    A vector of indices into the first dimension of var and accum.
        /// </param>
        /// <param name="lr">
        ///    Learning rate. Must be a scalar.
        /// </param>
        /// <param name="l1">
        ///    L1 regularization. Must be a scalar.
        /// </param>
        /// <param name="l2">
        ///    L2 regularization. Must be a scalar.
        /// </param>
        /// <param name="global_step">
        ///    Training step number. Must be a scalar.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseApplyAdagradDA'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, updating of the var and accum tensors will be protected by
        ///    a lock; otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor sparse_apply_adagrad_d_a (Tensor var, Tensor gradient_accumulator, Tensor gradient_squared_accumulator, Tensor grad, Tensor indices, Tensor lr, Tensor l1, Tensor l2, Tensor global_step, bool? use_locking = null, string name = "SparseApplyAdagradDA")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["gradient_accumulator"] = gradient_accumulator;
            dict["gradient_squared_accumulator"] = gradient_squared_accumulator;
            dict["grad"] = grad;
            dict["indices"] = indices;
            dict["lr"] = lr;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["global_step"] = global_step;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("SparseApplyAdagradDA", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update '*var' according to the centered RMSProp algorithm.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="mg">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="ms">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="mom">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="rho">
        ///    Decay rate. Must be a scalar.
        /// </param>
        /// <param name="momentum">
        /// </param>
        /// <param name="epsilon">
        ///    Ridge term. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="indices">
        ///    A vector of indices into the first dimension of var, ms and mom.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseApplyCenteredRMSProp'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var, mg, ms, and mom tensors is
        ///    protected by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The centered RMSProp algorithm uses an estimate of the centered second moment
        ///    (i.e., the variance) for normalization, as opposed to regular RMSProp, which
        ///    uses the (uncentered) second moment. This often helps with training, but is
        ///    slightly more expensive in terms of computation and memory.
        ///    
        ///    Note that in dense implementation of this algorithm, mg, ms, and mom will
        ///    update even if the grad is zero, but in this sparse implementation, mg, ms,
        ///    and mom will not update in iterations during which the grad is zero.
        ///    
        ///    mean_square = decay * mean_square + (1-decay) * gradient ** 2
        ///    mean_grad = decay * mean_grad + (1-decay) * gradient
        ///    Delta = learning_rate * gradient / sqrt(mean_square + epsilon - mean_grad ** 2)
        ///    
        ///    $$ms &amp;lt;- rho * ms_{t-1} + (1-rho) * grad * grad$$
        ///    $$mom &amp;lt;- momentum * mom_{t-1} + lr * grad / sqrt(ms + epsilon)$$
        ///    $$var &amp;lt;- var - mom$$
        /// </remarks>
        public static Tensor sparse_apply_centered_r_m_s_prop (Tensor var, Tensor mg, Tensor ms, Tensor mom, Tensor lr, Tensor rho, Tensor momentum, Tensor epsilon, Tensor grad, Tensor indices, bool? use_locking = null, string name = "SparseApplyCenteredRMSProp")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["mg"] = mg;
            dict["ms"] = ms;
            dict["mom"] = mom;
            dict["lr"] = lr;
            dict["rho"] = rho;
            dict["momentum"] = momentum;
            dict["epsilon"] = epsilon;
            dict["grad"] = grad;
            dict["indices"] = indices;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("SparseApplyCenteredRMSProp", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update relevant entries in '*var' according to the Ftrl-proximal scheme.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="linear">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="indices">
        ///    A vector of indices into the first dimension of var and accum.
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="l1">
        ///    L1 regularization. Must be a scalar.
        /// </param>
        /// <param name="l2">
        ///    L2 regularization. Must be a scalar.
        /// </param>
        /// <param name="lr_power">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseApplyFtrl'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var and accum tensors will be protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    That is for rows we have grad for, we update var, accum and linear as follows:
        ///    $$accum_new = accum + grad * grad$$
        ///    $$linear += grad + (accum_{new}^{-lr_{power}} - accum^{-lr_{power}} / lr * var$$
        ///    $$quadratic = 1.0 / (accum_{new}^{lr_{power}} * lr) + 2 * l2$$
        ///    $$var = (sign(linear) * l1 - linear) / quadratic\ if\ |linear| &amp;gt; l1\ else\ 0.0$$
        ///    $$accum = accum_{new}$$
        /// </remarks>
        public static Tensor sparse_apply_ftrl (Tensor var, Tensor accum, Tensor linear, Tensor grad, Tensor indices, Tensor lr, Tensor l1, Tensor l2, Tensor lr_power, bool? use_locking = null, string name = "SparseApplyFtrl")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["linear"] = linear;
            dict["grad"] = grad;
            dict["indices"] = indices;
            dict["lr"] = lr;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["lr_power"] = lr_power;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("SparseApplyFtrl", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update relevant entries in '*var' according to the Ftrl-proximal scheme.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="linear">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="indices">
        ///    A vector of indices into the first dimension of var and accum.
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="l1">
        ///    L1 regularization. Must be a scalar.
        /// </param>
        /// <param name="l2">
        ///    L2 shrinkage regulariation. Must be a scalar.
        /// </param>
        /// <param name="l2_shrinkage">
        /// </param>
        /// <param name="lr_power">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseApplyFtrlV2'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var and accum tensors will be protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    That is for rows we have grad for, we update var, accum and linear as follows:
        ///    grad_with_shrinkage = grad + 2 * l2_shrinkage * var
        ///    accum_new = accum + grad_with_shrinkage * grad_with_shrinkage
        ///    linear += grad_with_shrinkage +
        ///    (accum_new^(-lr_power) - accum^(-lr_power)) / lr * var
        ///    quadratic = 1.0 / (accum_new^(lr_power) * lr) + 2 * l2
        ///    var = (sign(linear) * l1 - linear) / quadratic if |linear| &amp;gt; l1 else 0.0
        ///    accum = accum_new
        /// </remarks>
        public static Tensor sparse_apply_ftrl_v2 (Tensor var, Tensor accum, Tensor linear, Tensor grad, Tensor indices, Tensor lr, Tensor l1, Tensor l2, Tensor l2_shrinkage, Tensor lr_power, bool? use_locking = null, string name = "SparseApplyFtrlV2")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["linear"] = linear;
            dict["grad"] = grad;
            dict["indices"] = indices;
            dict["lr"] = lr;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["l2_shrinkage"] = l2_shrinkage;
            dict["lr_power"] = lr_power;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("SparseApplyFtrlV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update relevant entries in '*var' and '*accum' according to the momentum scheme.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Learning rate. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="indices">
        ///    A vector of indices into the first dimension of var and accum.
        /// </param>
        /// <param name="momentum">
        ///    Momentum. Must be a scalar.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseApplyMomentum'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var and accum tensors will be protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <param name="use_nesterov">
        ///    If <c>True</c>, the tensor passed to compute grad will be
        ///    var - lr * momentum * accum, so in the end, the var you get is actually
        ///    var - lr * momentum * accum.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Set use_nesterov = True if you want to use Nesterov momentum.
        ///    
        ///    That is for rows we have grad for, we update var and accum as follows:
        ///    
        ///    $$accum = accum * momentum + grad$$
        ///    $$var -= lr * accum$$
        /// </remarks>
        public static Tensor sparse_apply_momentum (Tensor var, Tensor accum, Tensor lr, Tensor grad, Tensor indices, Tensor momentum, bool? use_locking = null, bool? use_nesterov = null, string name = "SparseApplyMomentum")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["lr"] = lr;
            dict["grad"] = grad;
            dict["indices"] = indices;
            dict["momentum"] = momentum;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            if (use_nesterov.HasValue)
                dict["use_nesterov"] = use_nesterov.Value;
            var op = _op_def_lib._apply_op_helper("SparseApplyMomentum", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Sparse update entries in '*var' and '*accum' according to FOBOS algorithm.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="accum">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Learning rate. Must be a scalar.
        /// </param>
        /// <param name="l1">
        ///    L1 regularization. Must be a scalar.
        /// </param>
        /// <param name="l2">
        ///    L2 regularization. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="indices">
        ///    A vector of indices into the first dimension of var and accum.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseApplyProximalAdagrad'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, updating of the var and accum tensors will be protected by
        ///    a lock; otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    That is for rows we have grad for, we update var and accum as follows:
        ///    $$accum += grad * grad$$
        ///    $$prox_v = var$$
        ///    $$prox_v -= lr * grad * (1 / sqrt(accum))$$
        ///    $$var = sign(prox_v)/(1+lr*l2) * max{|prox_v|-lr*l1,0}$$
        /// </remarks>
        public static Tensor sparse_apply_proximal_adagrad (Tensor var, Tensor accum, Tensor lr, Tensor l1, Tensor l2, Tensor grad, Tensor indices, bool? use_locking = null, string name = "SparseApplyProximalAdagrad")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["accum"] = accum;
            dict["lr"] = lr;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["grad"] = grad;
            dict["indices"] = indices;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("SparseApplyProximalAdagrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Sparse update '*var' as FOBOS algorithm with fixed learning rate.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="alpha">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="l1">
        ///    L1 regularization. Must be a scalar.
        /// </param>
        /// <param name="l2">
        ///    L2 regularization. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="indices">
        ///    A vector of indices into the first dimension of var and accum.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseApplyProximalGradientDescent'.
        /// </param>
        /// <param name="use_locking">
        ///    If True, the subtraction will be protected by a lock;
        ///    otherwise the behavior is undefined, but may exhibit less contention.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    That is for rows we have grad for, we update var as follows:
        ///    $$prox_v = var - alpha * grad$$
        ///    $$var = sign(prox_v)/(1+alpha*l2) * max{|prox_v|-alpha*l1,0}$$
        /// </remarks>
        public static Tensor sparse_apply_proximal_gradient_descent (Tensor var, Tensor alpha, Tensor l1, Tensor l2, Tensor grad, Tensor indices, bool? use_locking = null, string name = "SparseApplyProximalGradientDescent")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["alpha"] = alpha;
            dict["l1"] = l1;
            dict["l2"] = l2;
            dict["grad"] = grad;
            dict["indices"] = indices;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("SparseApplyProximalGradientDescent", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Update '*var' according to the RMSProp algorithm.
        /// </summary>
        /// <param name="var">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="ms">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="mom">
        ///    Should be from a Variable().
        /// </param>
        /// <param name="lr">
        ///    Scaling factor. Must be a scalar.
        /// </param>
        /// <param name="rho">
        ///    Decay rate. Must be a scalar.
        /// </param>
        /// <param name="momentum">
        /// </param>
        /// <param name="epsilon">
        ///    Ridge term. Must be a scalar.
        /// </param>
        /// <param name="grad">
        ///    The gradient.
        /// </param>
        /// <param name="indices">
        ///    A vector of indices into the first dimension of var, ms and mom.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseApplyRMSProp'.
        /// </param>
        /// <param name="use_locking">
        ///    If <c>True</c>, updating of the var, ms, and mom tensors is protected
        ///    by a lock; otherwise the behavior is undefined, but may exhibit less
        ///    contention.
        /// </param>
        /// <returns>
        ///    Same as "var".
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Note that in dense implementation of this algorithm, ms and mom will
        ///    update even if the grad is zero, but in this sparse implementation, ms
        ///    and mom will not update in iterations during which the grad is zero.
        ///    
        ///    mean_square = decay * mean_square + (1-decay) * gradient ** 2
        ///    Delta = learning_rate * gradient / sqrt(mean_square + epsilon)
        ///    
        ///    $$ms &amp;lt;- rho * ms_{t-1} + (1-rho) * grad * grad$$
        ///    $$mom &amp;lt;- momentum * mom_{t-1} + lr * grad / sqrt(ms + epsilon)$$
        ///    $$var &amp;lt;- var - mom$$
        /// </remarks>
        public static Tensor sparse_apply_r_m_s_prop (Tensor var, Tensor ms, Tensor mom, Tensor lr, Tensor rho, Tensor momentum, Tensor epsilon, Tensor grad, Tensor indices, bool? use_locking = null, string name = "SparseApplyRMSProp")
        {
            var dict = new Dictionary<string, object>();
            dict["var"] = var;
            dict["ms"] = ms;
            dict["mom"] = mom;
            dict["lr"] = lr;
            dict["rho"] = rho;
            dict["momentum"] = momentum;
            dict["epsilon"] = epsilon;
            dict["grad"] = grad;
            dict["indices"] = indices;
            if (use_locking.HasValue)
                dict["use_locking"] = use_locking.Value;
            var op = _op_def_lib._apply_op_helper("SparseApplyRMSProp", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Concatenates a list of <c>SparseTensor</c> along the specified dimension.
        /// </summary>
        /// <param name="indices">
        ///    2-D.  Indices of each input <c>SparseTensor</c>.
        /// </param>
        /// <param name="values">
        ///    1-D.  Non-empty values of each <c>SparseTensor</c>.
        /// </param>
        /// <param name="shapes">
        ///    1-D.  Shapes of each <c>SparseTensor</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseConcat'.
        /// </param>
        /// <param name="concat_dim">
        ///    Optional argument
        ///    Dimension to concatenate along. Must be in range [-rank, rank),
        ///    where rank is the number of dimensions in each input <c>SparseTensor</c>.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output_indices : 2-D.  Indices of the concatenated <c>SparseTensor</c>.
        ///    output_values : 1-D.  Non-empty values of the concatenated <c>SparseTensor</c>.
        ///    output_shape : 1-D.  Shape of the concatenated <c>SparseTensor</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Concatenation is with respect to the dense versions of these sparse tensors.
        ///    It is assumed that each input is a <c>SparseTensor</c> whose elements are ordered
        ///    along increasing dimension number.
        ///    
        ///    All inputs' shapes must match, except for the concat dimension.  The
        ///    <c>indices</c>, <c>values</c>, and <c>shapes</c> lists must have the same length.
        ///    
        ///    The output shape is identical to the inputs', except along the concat
        ///    dimension, where it is the sum of the inputs' sizes along that dimension.
        ///    
        ///    The output elements will be resorted to preserve the sort order along
        ///    increasing dimension number.
        ///    
        ///    This op runs in <c>O(M log M)</c> time, where <c>M</c> is the total number of non-empty
        ///    values across all inputs. This is due to the need for an internal sort in
        ///    order to concatenate efficiently across an arbitrary dimension.
        ///    
        ///    For example, if <c>concat_dim = 1</c> and the inputs are
        ///    
        ///    sp_inputs[0]: shape = [2, 3]
        ///    [0, 2]: "a"
        ///    [1, 0]: "b"
        ///    [1, 1]: "c"
        ///    
        ///    sp_inputs[1]: shape = [2, 4]
        ///    [0, 1]: "d"
        ///    [0, 2]: "e"
        ///    
        ///    then the output will be
        ///    
        ///    shape = [2, 7]
        ///    [0, 2]: "a"
        ///    [0, 4]: "d"
        ///    [0, 5]: "e"
        ///    [1, 0]: "b"
        ///    [1, 1]: "c"
        ///    
        ///    Graphically this is equivalent to doing
        ///    
        ///    [    a] concat [  d e  ] = [    a   d e  ]
        ///    [b c  ]        [       ]   [b c          ]
        /// </remarks>
        public static (Tensor output_indices, Tensor output_values, Tensor output_shape) sparse_concat (Tensor[] indices, Tensor[] values, Tensor[] shapes, int concat_dim, string name = "SparseConcat")
        {
            var dict = new Dictionary<string, object>();
            dict["indices"] = indices;
            dict["values"] = values;
            dict["shapes"] = shapes;
            dict["concat_dim"] = concat_dim;
            var op = _op_def_lib._apply_op_helper("SparseConcat", name: name, keywords: dict);
            int _idx = 0;
            var output_indices = op.outputs[_idx++];
            var output_values = op.outputs[_idx++];
            var output_shape = op.outputs[_idx++];
            return (output_indices, output_values, output_shape);
        }

        /// <summary>
        ///    A conditional accumulator for aggregating sparse gradients.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseConditionalAccumulator'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The type of the value being accumulated.
        /// </param>
        /// <param name="shape">
        ///    Optional argument
        ///    The shape of the values.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this accumulator is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this accumulator will be shared under the given name
        ///    across multiple sessions.
        /// </param>
        /// <returns>
        ///    The handle to the accumulator.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The accumulator accepts gradients marked with local_step greater or
        ///    equal to the most recent global_step known to the accumulator. The
        ///    average can be extracted from the accumulator, provided sufficient
        ///    gradients have been accumulated. Extracting the average automatically
        ///    resets the aggregate to 0, and increments the global_step recorded by
        ///    the accumulator.
        /// </remarks>
        public static Tensor sparse_conditional_accumulator (TF_DataType dtype, TensorShape shape, string container = null, string shared_name = null, string name = "SparseConditionalAccumulator")
        {
            var dict = new Dictionary<string, object>();
            dict["dtype"] = dtype;
            dict["shape"] = shape;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("SparseConditionalAccumulator", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Generates sparse cross from a list of sparse and dense tensors.
        /// </summary>
        /// <param name="indices">
        ///    2-D.  Indices of each input <c>SparseTensor</c>.
        /// </param>
        /// <param name="values">
        ///    1-D.   values of each <c>SparseTensor</c>.
        /// </param>
        /// <param name="shapes">
        ///    1-D.   Shapes of each <c>SparseTensor</c>.
        /// </param>
        /// <param name="dense_inputs">
        ///    2-D.    Columns represented by dense <c>Tensor</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseCross'.
        /// </param>
        /// <param name="hashed_output">
        ///    Optional argument
        ///    If true, returns the hash of the cross instead of the string.
        ///    This will allow us avoiding string manipulations.
        /// </param>
        /// <param name="num_buckets">
        ///    Optional argument
        ///    It is used if hashed_output is true.
        ///    output = hashed_value%num_buckets if num_buckets &amp;gt; 0 else hashed_value.
        /// </param>
        /// <param name="hash_key">
        ///    Optional argument
        ///    Specify the hash_key that will be used by the <c>FingerprintCat64</c>
        ///    function to combine the crosses fingerprints.
        /// </param>
        /// <param name="out_type">
        ///    Optional argument
        /// </param>
        /// <param name="internal_type">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output_indices : 2-D.  Indices of the concatenated <c>SparseTensor</c>.
        ///    output_values : 1-D.  Non-empty values of the concatenated or hashed
        ///    <c>SparseTensor</c>.
        ///    output_shape : 1-D.  Shape of the concatenated <c>SparseTensor</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    The op takes two lists, one of 2D <c>SparseTensor</c> and one of 2D <c>Tensor</c>, each
        ///    representing features of one feature column. It outputs a 2D <c>SparseTensor</c> with
        ///    the batchwise crosses of these features.
        ///    
        ///    For example, if the inputs are
        ///    
        ///    inputs[0]: SparseTensor with shape = [2, 2]
        ///    [0, 0]: "a"
        ///    [1, 0]: "b"
        ///    [1, 1]: "c"
        ///    
        ///    inputs[1]: SparseTensor with shape = [2, 1]
        ///    [0, 0]: "d"
        ///    [1, 0]: "e"
        ///    
        ///    inputs[2]: Tensor [["f"], ["g"]]
        ///    
        ///    then the output will be
        ///    
        ///    shape = [2, 2]
        ///    [0, 0]: "a_X_d_X_f"
        ///    [1, 0]: "b_X_e_X_g"
        ///    [1, 1]: "c_X_e_X_g"
        ///    
        ///    if hashed_output=true then the output will be
        ///    
        ///    shape = [2, 2]
        ///    [0, 0]: FingerprintCat64(
        ///    Fingerprint64("f"), FingerprintCat64(
        ///    Fingerprint64("d"), Fingerprint64("a")))
        ///    [1, 0]: FingerprintCat64(
        ///    Fingerprint64("g"), FingerprintCat64(
        ///    Fingerprint64("e"), Fingerprint64("b")))
        ///    [1, 1]: FingerprintCat64(
        ///    Fingerprint64("g"), FingerprintCat64(
        ///    Fingerprint64("e"), Fingerprint64("c")))
        /// </remarks>
        public static (Tensor output_indices, Tensor output_values, Tensor output_shape) sparse_cross (Tensor[] indices, Tensor[] values, Tensor[] shapes, Tensor[] dense_inputs, bool hashed_output, int num_buckets, int hash_key, TF_DataType out_type, TF_DataType internal_type, string name = "SparseCross")
        {
            var dict = new Dictionary<string, object>();
            dict["indices"] = indices;
            dict["values"] = values;
            dict["shapes"] = shapes;
            dict["dense_inputs"] = dense_inputs;
            dict["hashed_output"] = hashed_output;
            dict["num_buckets"] = num_buckets;
            dict["hash_key"] = hash_key;
            dict["out_type"] = out_type;
            dict["internal_type"] = internal_type;
            var op = _op_def_lib._apply_op_helper("SparseCross", name: name, keywords: dict);
            int _idx = 0;
            var output_indices = op.outputs[_idx++];
            var output_values = op.outputs[_idx++];
            var output_shape = op.outputs[_idx++];
            return (output_indices, output_values, output_shape);
        }

        /// <summary>
        ///    Adds up a SparseTensor and a dense Tensor, using these special rules:
        /// </summary>
        /// <param name="sp_indices">
        ///    2-D.  <c>N x R</c> matrix with the indices of non-empty values in a
        ///    SparseTensor, possibly not in canonical ordering.
        /// </param>
        /// <param name="sp_values">
        ///    1-D.  <c>N</c> non-empty values corresponding to <c>sp_indices</c>.
        /// </param>
        /// <param name="sp_shape">
        ///    1-D.  Shape of the input SparseTensor.
        /// </param>
        /// <param name="dense">
        ///    <c>R</c>-D.  The dense Tensor operand.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseDenseCwiseAdd'.
        /// </param>
        /// <returns>
        ///    1-D.  The <c>N</c> values that are operated on.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    (1) Broadcasts the dense side to have the same shape as the sparse side, if
        ///    eligible;
        ///    (2) Then, only the dense values pointed to by the indices of the SparseTensor
        ///    participate in the cwise addition.
        ///    
        ///    By these rules, the result is a logical SparseTensor with exactly the same
        ///    indices and shape, but possibly with different non-zero values.  The output of
        ///    this Op is the resultant non-zero values.
        /// </remarks>
        public static Tensor sparse_dense_cwise_add (Tensor sp_indices, Tensor sp_values, Tensor sp_shape, Tensor dense, string name = "SparseDenseCwiseAdd")
        {
            var dict = new Dictionary<string, object>();
            dict["sp_indices"] = sp_indices;
            dict["sp_values"] = sp_values;
            dict["sp_shape"] = sp_shape;
            dict["dense"] = dense;
            var op = _op_def_lib._apply_op_helper("SparseDenseCwiseAdd", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Component-wise divides a SparseTensor by a dense Tensor.
        /// </summary>
        /// <param name="sp_indices">
        ///    2-D.  <c>N x R</c> matrix with the indices of non-empty values in a
        ///    SparseTensor, possibly not in canonical ordering.
        /// </param>
        /// <param name="sp_values">
        ///    1-D.  <c>N</c> non-empty values corresponding to <c>sp_indices</c>.
        /// </param>
        /// <param name="sp_shape">
        ///    1-D.  Shape of the input SparseTensor.
        /// </param>
        /// <param name="dense">
        ///    <c>R</c>-D.  The dense Tensor operand.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseDenseCwiseDiv'.
        /// </param>
        /// <returns>
        ///    1-D.  The <c>N</c> values that are operated on.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    *Limitation*: this Op only broadcasts the dense side to the sparse side, but not
        ///    the other direction.
        /// </remarks>
        public static Tensor sparse_dense_cwise_div (Tensor sp_indices, Tensor sp_values, Tensor sp_shape, Tensor dense, string name = "SparseDenseCwiseDiv")
        {
            var dict = new Dictionary<string, object>();
            dict["sp_indices"] = sp_indices;
            dict["sp_values"] = sp_values;
            dict["sp_shape"] = sp_shape;
            dict["dense"] = dense;
            var op = _op_def_lib._apply_op_helper("SparseDenseCwiseDiv", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Component-wise multiplies a SparseTensor by a dense Tensor.
        /// </summary>
        /// <param name="sp_indices">
        ///    2-D.  <c>N x R</c> matrix with the indices of non-empty values in a
        ///    SparseTensor, possibly not in canonical ordering.
        /// </param>
        /// <param name="sp_values">
        ///    1-D.  <c>N</c> non-empty values corresponding to <c>sp_indices</c>.
        /// </param>
        /// <param name="sp_shape">
        ///    1-D.  Shape of the input SparseTensor.
        /// </param>
        /// <param name="dense">
        ///    <c>R</c>-D.  The dense Tensor operand.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseDenseCwiseMul'.
        /// </param>
        /// <returns>
        ///    1-D.  The <c>N</c> values that are operated on.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The output locations corresponding to the implicitly zero elements in the sparse
        ///    tensor will be zero (i.e., will not take up storage space), regardless of the
        ///    contents of the dense tensor (even if it's +/-INF and that INF*0 == NaN).
        ///    
        ///    *Limitation*: this Op only broadcasts the dense side to the sparse side, but not
        ///    the other direction.
        /// </remarks>
        public static Tensor sparse_dense_cwise_mul (Tensor sp_indices, Tensor sp_values, Tensor sp_shape, Tensor dense, string name = "SparseDenseCwiseMul")
        {
            var dict = new Dictionary<string, object>();
            dict["sp_indices"] = sp_indices;
            dict["sp_values"] = sp_values;
            dict["sp_shape"] = sp_shape;
            dict["dense"] = dense;
            var op = _op_def_lib._apply_op_helper("SparseDenseCwiseMul", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Fills empty rows in the input 2-D <c>SparseTensor</c> with a default value.
        /// </summary>
        /// <param name="indices">
        ///    2-D. the indices of the sparse tensor.
        /// </param>
        /// <param name="values">
        ///    1-D. the values of the sparse tensor.
        /// </param>
        /// <param name="dense_shape">
        ///    1-D. the shape of the sparse tensor.
        /// </param>
        /// <param name="default_value">
        ///    0-D. default value to insert into location <c>[row, 0, ..., 0]</c>
        ///    for rows missing from the input sparse tensor.
        ///    output indices: 2-D. the indices of the filled sparse tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseFillEmptyRows'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output_indices :
        ///    output_values : 1-D. the values of the filled sparse tensor.
        ///    empty_row_indicator : 1-D. whether the dense row was missing in the
        ///    input sparse tensor.
        ///    reverse_index_map : 1-D. a map from the input indices to the output indices.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    The input <c>SparseTensor</c> is represented via the tuple of inputs
        ///    (<c>indices</c>, <c>values</c>, <c>dense_shape</c>).  The output <c>SparseTensor</c> has the
        ///    same <c>dense_shape</c> but with indices <c>output_indices</c> and values
        ///    <c>output_values</c>.
        ///    
        ///    This op inserts a single entry for every row that doesn't have any values.
        ///    The index is created as <c>[row, 0, ..., 0]</c> and the inserted value
        ///    is <c>default_value</c>.
        ///    
        ///    For example, suppose <c>sp_input</c> has shape <c>[5, 6]</c> and non-empty values:
        ///    
        ///    [0, 1]: a
        ///    [0, 3]: b
        ///    [2, 0]: c
        ///    [3, 1]: d
        ///    
        ///    Rows 1 and 4 are empty, so the output will be of shape <c>[5, 6]</c> with values:
        ///    
        ///    [0, 1]: a
        ///    [0, 3]: b
        ///    [1, 0]: default_value
        ///    [2, 0]: c
        ///    [3, 1]: d
        ///    [4, 0]: default_value
        ///    
        ///    The output <c>SparseTensor</c> will be in row-major order and will have the
        ///    same shape as the input.
        ///    
        ///    This op also returns an indicator vector shaped <c>[dense_shape[0]]</c> such that
        ///    
        ///    empty_row_indicator[i] = True iff row i was an empty row.
        ///    
        ///    And a reverse index map vector shaped <c>[indices.shape[0]]</c> that is used during
        ///    backpropagation,
        ///    
        ///    reverse_index_map[j] = out_j s.t. indices[j, :] == output_indices[out_j, :]
        /// </remarks>
        public static (Tensor output_indices, Tensor output_values, Tensor empty_row_indicator, Tensor reverse_index_map) sparse_fill_empty_rows (Tensor indices, Tensor values, Tensor dense_shape, Tensor default_value, string name = "SparseFillEmptyRows")
        {
            var dict = new Dictionary<string, object>();
            dict["indices"] = indices;
            dict["values"] = values;
            dict["dense_shape"] = dense_shape;
            dict["default_value"] = default_value;
            var op = _op_def_lib._apply_op_helper("SparseFillEmptyRows", name: name, keywords: dict);
            int _idx = 0;
            var output_indices = op.outputs[_idx++];
            var output_values = op.outputs[_idx++];
            var empty_row_indicator = op.outputs[_idx++];
            var reverse_index_map = op.outputs[_idx++];
            return (output_indices, output_values, empty_row_indicator, reverse_index_map);
        }

        /// <summary>
        ///    The gradient of SparseFillEmptyRows.
        /// </summary>
        /// <param name="reverse_index_map">
        ///    1-D.  The reverse index map from SparseFillEmptyRows.
        /// </param>
        /// <param name="grad_values">
        ///    1-D.  The gradients from backprop.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseFillEmptyRowsGrad'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    d_values : 1-D.  The backprop into values.
        ///    d_default_value : 0-D.  The backprop into default_value.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Takes vectors reverse_index_map, shaped <c>[N]</c>, and grad_values,
        ///    shaped <c>[N_full]</c>, where <c>N_full &amp;gt;= N</c> and copies data into either
        ///    <c>d_values</c> or <c>d_default_value</c>.  Here <c>d_values</c> is shaped <c>[N]</c> and
        ///    <c>d_default_value</c> is a scalar.
        ///    
        ///    d_values[j] = grad_values[reverse_index_map[j]]
        ///    d_default_value = sum_{k : 0 .. N_full - 1} (
        ///    grad_values[k] * 1{k not in reverse_index_map})
        /// </remarks>
        public static (Tensor d_values, Tensor d_default_value) sparse_fill_empty_rows_grad (Tensor reverse_index_map, Tensor grad_values, string name = "SparseFillEmptyRowsGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["reverse_index_map"] = reverse_index_map;
            dict["grad_values"] = grad_values;
            var op = _op_def_lib._apply_op_helper("SparseFillEmptyRowsGrad", name: name, keywords: dict);
            int _idx = 0;
            var d_values = op.outputs[_idx++];
            var d_default_value = op.outputs[_idx++];
            return (d_values, d_default_value);
        }

        /// <summary>
        ///    Multiply matrix "a" by matrix "b".
        /// </summary>
        /// <param name="a">
        /// </param>
        /// <param name="b">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseMatMul'.
        /// </param>
        /// <param name="transpose_a">
        /// </param>
        /// <param name="transpose_b">
        /// </param>
        /// <param name="a_is_sparse">
        /// </param>
        /// <param name="b_is_sparse">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The inputs must be two-dimensional matrices and the inner dimension of "a" must
        ///    match the outer dimension of "b". Both "a" and "b" must be <c>Tensor</c>s not
        ///    <c>SparseTensor</c>s.  This op is optimized for the case where at least one of "a" or
        ///    "b" is sparse, in the sense that they have a large proportion of zero values.
        ///    The breakeven for using this versus a dense matrix multiply on one platform was
        ///    30% zero values in the sparse matrix.
        ///    
        ///    The gradient computation of this operation will only take advantage of sparsity
        ///    in the input gradient when that gradient comes from a Relu.
        /// </remarks>
        public static Tensor sparse_mat_mul (Tensor a, Tensor b, bool? transpose_a = null, bool? transpose_b = null, bool? a_is_sparse = null, bool? b_is_sparse = null, string name = "SparseMatMul")
        {
            var dict = new Dictionary<string, object>();
            dict["a"] = a;
            dict["b"] = b;
            if (transpose_a.HasValue)
                dict["transpose_a"] = transpose_a.Value;
            if (transpose_b.HasValue)
                dict["transpose_b"] = transpose_b.Value;
            if (a_is_sparse.HasValue)
                dict["a_is_sparse"] = a_is_sparse.Value;
            if (b_is_sparse.HasValue)
                dict["b_is_sparse"] = b_is_sparse.Value;
            var op = _op_def_lib._apply_op_helper("SparseMatMul", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the max of elements across dimensions of a SparseTensor.
        /// </summary>
        /// <param name="input_indices">
        ///    2-D.  <c>N x R</c> matrix with the indices of non-empty values in a
        ///    SparseTensor, possibly not in canonical ordering.
        /// </param>
        /// <param name="input_values">
        ///    1-D.  <c>N</c> non-empty values corresponding to <c>input_indices</c>.
        /// </param>
        /// <param name="input_shape">
        ///    1-D.  Shape of the input SparseTensor.
        /// </param>
        /// <param name="reduction_axes">
        ///    1-D.  Length-<c>K</c> vector containing the reduction axes.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseReduceMax'.
        /// </param>
        /// <param name="keep_dims">
        ///    If true, retain reduced dimensions with length 1.
        /// </param>
        /// <returns>
        ///    <c>R-K</c>-D.  The reduced Tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This Op takes a SparseTensor and is the sparse counterpart to
        ///    <c>tf.reduce_max()</c>.  In particular, this Op also returns a dense <c>Tensor</c>
        ///    instead of a sparse one.
        ///    
        ///    Reduces <c>sp_input</c> along the dimensions given in <c>reduction_axes</c>.  Unless
        ///    <c>keep_dims</c> is true, the rank of the tensor is reduced by 1 for each entry in
        ///    <c>reduction_axes</c>. If <c>keep_dims</c> is true, the reduced dimensions are retained
        ///    with length 1.
        ///    
        ///    If <c>reduction_axes</c> has no entries, all dimensions are reduced, and a tensor
        ///    with a single element is returned.  Additionally, the axes can be negative,
        ///    which are interpreted according to the indexing rules in Python.
        /// </remarks>
        public static Tensor sparse_reduce_max (Tensor input_indices, Tensor input_values, Tensor input_shape, Tensor reduction_axes, bool? keep_dims = null, string name = "SparseReduceMax")
        {
            var dict = new Dictionary<string, object>();
            dict["input_indices"] = input_indices;
            dict["input_values"] = input_values;
            dict["input_shape"] = input_shape;
            dict["reduction_axes"] = reduction_axes;
            if (keep_dims.HasValue)
                dict["keep_dims"] = keep_dims.Value;
            var op = _op_def_lib._apply_op_helper("SparseReduceMax", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the max of elements across dimensions of a SparseTensor.
        /// </summary>
        /// <param name="input_indices">
        ///    2-D.  <c>N x R</c> matrix with the indices of non-empty values in a
        ///    SparseTensor, possibly not in canonical ordering.
        /// </param>
        /// <param name="input_values">
        ///    1-D.  <c>N</c> non-empty values corresponding to <c>input_indices</c>.
        /// </param>
        /// <param name="input_shape">
        ///    1-D.  Shape of the input SparseTensor.
        /// </param>
        /// <param name="reduction_axes">
        ///    1-D.  Length-<c>K</c> vector containing the reduction axes.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseReduceMaxSparse'.
        /// </param>
        /// <param name="keep_dims">
        ///    If true, retain reduced dimensions with length 1.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output_indices :
        ///    output_values :
        ///    output_shape :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    This Op takes a SparseTensor and is the sparse counterpart to
        ///    <c>tf.reduce_max()</c>.  In contrast to SparseReduceMax, this Op returns a
        ///    SparseTensor.
        ///    
        ///    Reduces <c>sp_input</c> along the dimensions given in <c>reduction_axes</c>.  Unless
        ///    <c>keep_dims</c> is true, the rank of the tensor is reduced by 1 for each entry in
        ///    <c>reduction_axes</c>. If <c>keep_dims</c> is true, the reduced dimensions are retained
        ///    with length 1.
        ///    
        ///    If <c>reduction_axes</c> has no entries, all dimensions are reduced, and a tensor
        ///    with a single element is returned.  Additionally, the axes can be negative,
        ///    which are interpreted according to the indexing rules in Python.
        /// </remarks>
        public static (Tensor output_indices, Tensor output_values, Tensor output_shape) sparse_reduce_max_sparse (Tensor input_indices, Tensor input_values, Tensor input_shape, Tensor reduction_axes, bool? keep_dims = null, string name = "SparseReduceMaxSparse")
        {
            var dict = new Dictionary<string, object>();
            dict["input_indices"] = input_indices;
            dict["input_values"] = input_values;
            dict["input_shape"] = input_shape;
            dict["reduction_axes"] = reduction_axes;
            if (keep_dims.HasValue)
                dict["keep_dims"] = keep_dims.Value;
            var op = _op_def_lib._apply_op_helper("SparseReduceMaxSparse", name: name, keywords: dict);
            int _idx = 0;
            var output_indices = op.outputs[_idx++];
            var output_values = op.outputs[_idx++];
            var output_shape = op.outputs[_idx++];
            return (output_indices, output_values, output_shape);
        }

        /// <summary>
        ///    Computes the sum of elements across dimensions of a SparseTensor.
        /// </summary>
        /// <param name="input_indices">
        ///    2-D.  <c>N x R</c> matrix with the indices of non-empty values in a
        ///    SparseTensor, possibly not in canonical ordering.
        /// </param>
        /// <param name="input_values">
        ///    1-D.  <c>N</c> non-empty values corresponding to <c>input_indices</c>.
        /// </param>
        /// <param name="input_shape">
        ///    1-D.  Shape of the input SparseTensor.
        /// </param>
        /// <param name="reduction_axes">
        ///    1-D.  Length-<c>K</c> vector containing the reduction axes.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseReduceSum'.
        /// </param>
        /// <param name="keep_dims">
        ///    If true, retain reduced dimensions with length 1.
        /// </param>
        /// <returns>
        ///    <c>R-K</c>-D.  The reduced Tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This Op takes a SparseTensor and is the sparse counterpart to
        ///    <c>tf.reduce_sum()</c>.  In particular, this Op also returns a dense <c>Tensor</c>
        ///    instead of a sparse one.
        ///    
        ///    Reduces <c>sp_input</c> along the dimensions given in <c>reduction_axes</c>.  Unless
        ///    <c>keep_dims</c> is true, the rank of the tensor is reduced by 1 for each entry in
        ///    <c>reduction_axes</c>. If <c>keep_dims</c> is true, the reduced dimensions are retained
        ///    with length 1.
        ///    
        ///    If <c>reduction_axes</c> has no entries, all dimensions are reduced, and a tensor
        ///    with a single element is returned.  Additionally, the axes can be negative,
        ///    which are interpreted according to the indexing rules in Python.
        /// </remarks>
        public static Tensor sparse_reduce_sum (Tensor input_indices, Tensor input_values, Tensor input_shape, Tensor reduction_axes, bool? keep_dims = null, string name = "SparseReduceSum")
        {
            var dict = new Dictionary<string, object>();
            dict["input_indices"] = input_indices;
            dict["input_values"] = input_values;
            dict["input_shape"] = input_shape;
            dict["reduction_axes"] = reduction_axes;
            if (keep_dims.HasValue)
                dict["keep_dims"] = keep_dims.Value;
            var op = _op_def_lib._apply_op_helper("SparseReduceSum", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the sum of elements across dimensions of a SparseTensor.
        /// </summary>
        /// <param name="input_indices">
        ///    2-D.  <c>N x R</c> matrix with the indices of non-empty values in a
        ///    SparseTensor, possibly not in canonical ordering.
        /// </param>
        /// <param name="input_values">
        ///    1-D.  <c>N</c> non-empty values corresponding to <c>input_indices</c>.
        /// </param>
        /// <param name="input_shape">
        ///    1-D.  Shape of the input SparseTensor.
        /// </param>
        /// <param name="reduction_axes">
        ///    1-D.  Length-<c>K</c> vector containing the reduction axes.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseReduceSumSparse'.
        /// </param>
        /// <param name="keep_dims">
        ///    If true, retain reduced dimensions with length 1.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output_indices :
        ///    output_values :
        ///    output_shape :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    This Op takes a SparseTensor and is the sparse counterpart to
        ///    <c>tf.reduce_sum()</c>.  In contrast to SparseReduceSum, this Op returns a
        ///    SparseTensor.
        ///    
        ///    Reduces <c>sp_input</c> along the dimensions given in <c>reduction_axes</c>.  Unless
        ///    <c>keep_dims</c> is true, the rank of the tensor is reduced by 1 for each entry in
        ///    <c>reduction_axes</c>. If <c>keep_dims</c> is true, the reduced dimensions are retained
        ///    with length 1.
        ///    
        ///    If <c>reduction_axes</c> has no entries, all dimensions are reduced, and a tensor
        ///    with a single element is returned.  Additionally, the axes can be negative,
        ///    which are interpreted according to the indexing rules in Python.
        /// </remarks>
        public static (Tensor output_indices, Tensor output_values, Tensor output_shape) sparse_reduce_sum_sparse (Tensor input_indices, Tensor input_values, Tensor input_shape, Tensor reduction_axes, bool? keep_dims = null, string name = "SparseReduceSumSparse")
        {
            var dict = new Dictionary<string, object>();
            dict["input_indices"] = input_indices;
            dict["input_values"] = input_values;
            dict["input_shape"] = input_shape;
            dict["reduction_axes"] = reduction_axes;
            if (keep_dims.HasValue)
                dict["keep_dims"] = keep_dims.Value;
            var op = _op_def_lib._apply_op_helper("SparseReduceSumSparse", name: name, keywords: dict);
            int _idx = 0;
            var output_indices = op.outputs[_idx++];
            var output_values = op.outputs[_idx++];
            var output_shape = op.outputs[_idx++];
            return (output_indices, output_values, output_shape);
        }

        /// <summary>
        ///    Reorders a SparseTensor into the canonical, row-major ordering.
        /// </summary>
        /// <param name="input_indices">
        ///    2-D.  <c>N x R</c> matrix with the indices of non-empty values in a
        ///    SparseTensor, possibly not in canonical ordering.
        /// </param>
        /// <param name="input_values">
        ///    1-D.  <c>N</c> non-empty values corresponding to <c>input_indices</c>.
        /// </param>
        /// <param name="input_shape">
        ///    1-D.  Shape of the input SparseTensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseReorder'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output_indices : 2-D.  <c>N x R</c> matrix with the same indices as input_indices, but
        ///    in canonical row-major ordering.
        ///    output_values : 1-D.  <c>N</c> non-empty values corresponding to <c>output_indices</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Note that by convention, all sparse ops preserve the canonical ordering along
        ///    increasing dimension number. The only time ordering can be violated is during
        ///    manual manipulation of the indices and values vectors to add entries.
        ///    
        ///    Reordering does not affect the shape of the SparseTensor.
        ///    
        ///    If the tensor has rank <c>R</c> and <c>N</c> non-empty values, <c>input_indices</c> has
        ///    shape <c>[N, R]</c>, input_values has length <c>N</c>, and input_shape has length <c>R</c>.
        /// </remarks>
        public static (Tensor output_indices, Tensor output_values) sparse_reorder (Tensor input_indices, Tensor input_values, Tensor input_shape, string name = "SparseReorder")
        {
            var dict = new Dictionary<string, object>();
            dict["input_indices"] = input_indices;
            dict["input_values"] = input_values;
            dict["input_shape"] = input_shape;
            var op = _op_def_lib._apply_op_helper("SparseReorder", name: name, keywords: dict);
            int _idx = 0;
            var output_indices = op.outputs[_idx++];
            var output_values = op.outputs[_idx++];
            return (output_indices, output_values);
        }

        /// <summary>
        ///    Reshapes a SparseTensor to represent values in a new dense shape.
        /// </summary>
        /// <param name="input_indices">
        ///    2-D.  <c>N x R_in</c> matrix with the indices of non-empty values in a
        ///    SparseTensor.
        /// </param>
        /// <param name="input_shape">
        ///    1-D.  <c>R_in</c> vector with the input SparseTensor's dense shape.
        /// </param>
        /// <param name="new_shape">
        ///    1-D.  <c>R_out</c> vector with the requested new dense shape.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseReshape'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output_indices : 2-D.  <c>N x R_out</c> matrix with the updated indices of non-empty
        ///    values in the output SparseTensor.
        ///    output_shape : 1-D.  <c>R_out</c> vector with the full dense shape of the output
        ///    SparseTensor.  This is the same as <c>new_shape</c> but with any -1 dimensions
        ///    filled in.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    This operation has the same semantics as reshape on the represented dense
        ///    tensor.  The <c>input_indices</c> are recomputed based on the requested <c>new_shape</c>.
        ///    
        ///    If one component of <c>new_shape</c> is the special value -1, the size of that
        ///    dimension is computed so that the total dense size remains constant.  At
        ///    most one component of <c>new_shape</c> can be -1.  The number of dense elements
        ///    implied by <c>new_shape</c> must be the same as the number of dense elements
        ///    originally implied by <c>input_shape</c>.
        ///    
        ///    Reshaping does not affect the order of values in the SparseTensor.
        ///    
        ///    If the input tensor has rank <c>R_in</c> and <c>N</c> non-empty values, and <c>new_shape</c>
        ///    has length <c>R_out</c>, then <c>input_indices</c> has shape <c>[N, R_in]</c>,
        ///    <c>input_shape</c> has length <c>R_in</c>, <c>output_indices</c> has shape <c>[N, R_out]</c>, and
        ///    <c>output_shape</c> has length <c>R_out</c>.
        /// </remarks>
        public static (Tensor output_indices, Tensor output_shape) sparse_reshape (Tensor input_indices, Tensor input_shape, Tensor new_shape, string name = "SparseReshape")
        {
            var dict = new Dictionary<string, object>();
            dict["input_indices"] = input_indices;
            dict["input_shape"] = input_shape;
            dict["new_shape"] = new_shape;
            var op = _op_def_lib._apply_op_helper("SparseReshape", name: name, keywords: dict);
            int _idx = 0;
            var output_indices = op.outputs[_idx++];
            var output_shape = op.outputs[_idx++];
            return (output_indices, output_shape);
        }

        /// <summary>
        ///    Computes the mean along sparse segments of a tensor.
        /// </summary>
        /// <param name="data">
        /// </param>
        /// <param name="indices">
        ///    A 1-D tensor. Has same rank as <c>segment_ids</c>.
        /// </param>
        /// <param name="segment_ids">
        ///    A 1-D tensor. Values should be sorted and can be repeated.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseSegmentMean'.
        /// </param>
        /// <returns>
        ///    Has same shape as data, except for dimension 0 which
        ///    has size <c>k</c>, the number of segments.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Read
        ///    [the section on segmentation](https://tensorflow.org/api_guides/python/math_ops#Segmentation)
        ///    for an explanation of segments.
        ///    
        ///    Like <c>SegmentMean</c>, but <c>segment_ids</c> can have rank less than <c>data</c>'s first
        ///    dimension, selecting a subset of dimension 0, specified by <c>indices</c>.
        /// </remarks>
        public static Tensor sparse_segment_mean (Tensor data, Tensor indices, Tensor segment_ids, string name = "SparseSegmentMean")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            dict["indices"] = indices;
            dict["segment_ids"] = segment_ids;
            var op = _op_def_lib._apply_op_helper("SparseSegmentMean", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes gradients for SparseSegmentMean.
        /// </summary>
        /// <param name="grad">
        ///    gradient propagated to the SparseSegmentMean op.
        /// </param>
        /// <param name="indices">
        ///    indices passed to the corresponding SparseSegmentMean op.
        /// </param>
        /// <param name="segment_ids">
        ///    segment_ids passed to the corresponding SparseSegmentMean op.
        /// </param>
        /// <param name="output_dim0">
        ///    dimension 0 of "data" passed to SparseSegmentMean op.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseSegmentMeanGrad'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Returns tensor "output" with same shape as grad, except for dimension 0 whose
        ///    value is output_dim0.
        /// </remarks>
        public static Tensor sparse_segment_mean_grad (Tensor grad, Tensor indices, Tensor segment_ids, Tensor output_dim0, string name = "SparseSegmentMeanGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["grad"] = grad;
            dict["indices"] = indices;
            dict["segment_ids"] = segment_ids;
            dict["output_dim0"] = output_dim0;
            var op = _op_def_lib._apply_op_helper("SparseSegmentMeanGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the mean along sparse segments of a tensor.
        /// </summary>
        /// <param name="data">
        /// </param>
        /// <param name="indices">
        ///    A 1-D tensor. Has same rank as <c>segment_ids</c>.
        /// </param>
        /// <param name="segment_ids">
        ///    A 1-D tensor. Values should be sorted and can be repeated.
        /// </param>
        /// <param name="num_segments">
        ///    Should equal the number of distinct segment IDs.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseSegmentMeanWithNumSegments'.
        /// </param>
        /// <returns>
        ///    Has same shape as data, except for dimension 0 which has size
        ///    <c>num_segments</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Like <c>SparseSegmentMean</c>, but allows missing ids in <c>segment_ids</c>. If an id is
        ///    misisng, the <c>output</c> tensor at that position will be zeroed.
        ///    
        ///    Read
        ///    [the section on segmentation](https://tensorflow.org/api_guides/python/math_ops#Segmentation)
        ///    for an explanation of segments.
        /// </remarks>
        public static Tensor sparse_segment_mean_with_num_segments (Tensor data, Tensor indices, Tensor segment_ids, Tensor num_segments, string name = "SparseSegmentMeanWithNumSegments")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            dict["indices"] = indices;
            dict["segment_ids"] = segment_ids;
            dict["num_segments"] = num_segments;
            var op = _op_def_lib._apply_op_helper("SparseSegmentMeanWithNumSegments", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the sum along sparse segments of a tensor divided by the sqrt of N.
        /// </summary>
        /// <param name="data">
        /// </param>
        /// <param name="indices">
        ///    A 1-D tensor. Has same rank as <c>segment_ids</c>.
        /// </param>
        /// <param name="segment_ids">
        ///    A 1-D tensor. Values should be sorted and can be repeated.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseSegmentSqrtN'.
        /// </param>
        /// <returns>
        ///    Has same shape as data, except for dimension 0 which
        ///    has size <c>k</c>, the number of segments.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    N is the size of the segment being reduced.
        ///    
        ///    Read
        ///    [the section on segmentation](https://tensorflow.org/api_guides/python/math_ops#Segmentation)
        ///    for an explanation of segments.
        /// </remarks>
        public static Tensor sparse_segment_sqrt_n (Tensor data, Tensor indices, Tensor segment_ids, string name = "SparseSegmentSqrtN")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            dict["indices"] = indices;
            dict["segment_ids"] = segment_ids;
            var op = _op_def_lib._apply_op_helper("SparseSegmentSqrtN", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes gradients for SparseSegmentSqrtN.
        /// </summary>
        /// <param name="grad">
        ///    gradient propagated to the SparseSegmentSqrtN op.
        /// </param>
        /// <param name="indices">
        ///    indices passed to the corresponding SparseSegmentSqrtN op.
        /// </param>
        /// <param name="segment_ids">
        ///    segment_ids passed to the corresponding SparseSegmentSqrtN op.
        /// </param>
        /// <param name="output_dim0">
        ///    dimension 0 of "data" passed to SparseSegmentSqrtN op.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseSegmentSqrtNGrad'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Returns tensor "output" with same shape as grad, except for dimension 0 whose
        ///    value is output_dim0.
        /// </remarks>
        public static Tensor sparse_segment_sqrt_n_grad (Tensor grad, Tensor indices, Tensor segment_ids, Tensor output_dim0, string name = "SparseSegmentSqrtNGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["grad"] = grad;
            dict["indices"] = indices;
            dict["segment_ids"] = segment_ids;
            dict["output_dim0"] = output_dim0;
            var op = _op_def_lib._apply_op_helper("SparseSegmentSqrtNGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the sum along sparse segments of a tensor divided by the sqrt of N.
        /// </summary>
        /// <param name="data">
        /// </param>
        /// <param name="indices">
        ///    A 1-D tensor. Has same rank as <c>segment_ids</c>.
        /// </param>
        /// <param name="segment_ids">
        ///    A 1-D tensor. Values should be sorted and can be repeated.
        /// </param>
        /// <param name="num_segments">
        ///    Should equal the number of distinct segment IDs.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseSegmentSqrtNWithNumSegments'.
        /// </param>
        /// <returns>
        ///    Has same shape as data, except for dimension 0 which
        ///    has size <c>k</c>, the number of segments.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    N is the size of the segment being reduced.
        ///    
        ///    Like <c>SparseSegmentSqrtN</c>, but allows missing ids in <c>segment_ids</c>. If an id is
        ///    misisng, the <c>output</c> tensor at that position will be zeroed.
        ///    
        ///    Read
        ///    [the section on segmentation](https://tensorflow.org/api_guides/python/math_ops#Segmentation)
        ///    for an explanation of segments.
        /// </remarks>
        public static Tensor sparse_segment_sqrt_n_with_num_segments (Tensor data, Tensor indices, Tensor segment_ids, Tensor num_segments, string name = "SparseSegmentSqrtNWithNumSegments")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            dict["indices"] = indices;
            dict["segment_ids"] = segment_ids;
            dict["num_segments"] = num_segments;
            var op = _op_def_lib._apply_op_helper("SparseSegmentSqrtNWithNumSegments", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the sum along sparse segments of a tensor.
        /// </summary>
        /// <param name="data">
        /// </param>
        /// <param name="indices">
        ///    A 1-D tensor. Has same rank as <c>segment_ids</c>.
        /// </param>
        /// <param name="segment_ids">
        ///    A 1-D tensor. Values should be sorted and can be repeated.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseSegmentSum'.
        /// </param>
        /// <returns>
        ///    Has same shape as data, except for dimension 0 which
        ///    has size <c>k</c>, the number of segments.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Read
        ///    [the section on segmentation](https://tensorflow.org/api_guides/python/math_ops#Segmentation)
        ///    for an explanation of segments.
        ///    
        ///    Like <c>SegmentSum</c>, but <c>segment_ids</c> can have rank less than <c>data</c>'s first
        ///    dimension, selecting a subset of dimension 0, specified by <c>indices</c>.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    c = tf.constant([[1,2,3,4], [-1,-2,-3,-4], [5,6,7,8]])
        ///    
        ///    # Select two rows, one segment.
        ///    tf.sparse_segment_sum(c, tf.constant([0, 1]), tf.constant([0, 0]))
        ///    # =&amp;gt; [[0 0 0 0]]
        ///    
        ///    # Select two rows, two segment.
        ///    tf.sparse_segment_sum(c, tf.constant([0, 1]), tf.constant([0, 1]))
        ///    # =&amp;gt; [[ 1  2  3  4]
        ///    #     [-1 -2 -3 -4]]
        ///    
        ///    # Select all rows, two segments.
        ///    tf.sparse_segment_sum(c, tf.constant([0, 1, 2]), tf.constant([0, 0, 1]))
        ///    # =&amp;gt; [[0 0 0 0]
        ///    #     [5 6 7 8]]
        ///    
        ///    # Which is equivalent to:
        ///    tf.segment_sum(c, tf.constant([0, 0, 1]))
        ///   </code>
        /// </remarks>
        public static Tensor sparse_segment_sum (Tensor data, Tensor indices, Tensor segment_ids, string name = "SparseSegmentSum")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            dict["indices"] = indices;
            dict["segment_ids"] = segment_ids;
            var op = _op_def_lib._apply_op_helper("SparseSegmentSum", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the sum along sparse segments of a tensor.
        /// </summary>
        /// <param name="data">
        /// </param>
        /// <param name="indices">
        ///    A 1-D tensor. Has same rank as <c>segment_ids</c>.
        /// </param>
        /// <param name="segment_ids">
        ///    A 1-D tensor. Values should be sorted and can be repeated.
        /// </param>
        /// <param name="num_segments">
        ///    Should equal the number of distinct segment IDs.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseSegmentSumWithNumSegments'.
        /// </param>
        /// <returns>
        ///    Has same shape as data, except for dimension 0 which
        ///    has size <c>num_segments</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Like <c>SparseSegmentSum</c>, but allows missing ids in <c>segment_ids</c>. If an id is
        ///    misisng, the <c>output</c> tensor at that position will be zeroed.
        ///    
        ///    Read
        ///    [the section on segmentation](https://tensorflow.org/api_guides/python/math_ops#Segmentation)
        ///    for an explanation of segments.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    c = tf.constant([[1,2,3,4], [-1,-2,-3,-4], [5,6,7,8]])
        ///    
        ///    tf.sparse_segment_sum_with_num_segments(
        ///    c, tf.constant([0, 1]), tf.constant([0, 0]), num_segments=3)
        ///    # =&amp;gt; [[0 0 0 0]
        ///    #     [0 0 0 0]
        ///    #     [0 0 0 0]]
        ///    
        ///    tf.sparse_segment_sum_with_num_segments(c,
        ///    tf.constant([0, 1]),
        ///    tf.constant([0, 2],
        ///    num_segments=4))
        ///    # =&amp;gt; [[ 1  2  3  4]
        ///    #     [ 0  0  0  0]
        ///    #     [-1 -2 -3 -4]
        ///    #     [ 0  0  0  0]]
        ///   </code>
        /// </remarks>
        public static Tensor sparse_segment_sum_with_num_segments (Tensor data, Tensor indices, Tensor segment_ids, Tensor num_segments, string name = "SparseSegmentSumWithNumSegments")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            dict["indices"] = indices;
            dict["segment_ids"] = segment_ids;
            dict["num_segments"] = num_segments;
            var op = _op_def_lib._apply_op_helper("SparseSegmentSumWithNumSegments", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Slice a <c>SparseTensor</c> based on the <c>start</c> and <c>size</c>.
        /// </summary>
        /// <param name="indices">
        ///    2-D tensor represents the indices of the sparse tensor.
        /// </param>
        /// <param name="values">
        ///    1-D tensor represents the values of the sparse tensor.
        /// </param>
        /// <param name="shape">
        ///    1-D. tensor represents the shape of the sparse tensor.
        /// </param>
        /// <param name="start">
        ///    1-D. tensor represents the start of the slice.
        /// </param>
        /// <param name="size">
        ///    1-D. tensor represents the size of the slice.
        ///    output indices: A list of 1-D tensors represents the indices of the output
        ///    sparse tensors.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseSlice'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output_indices :
        ///    output_values : A list of 1-D tensors represents the values of the output sparse
        ///    tensors.
        ///    output_shape : A list of 1-D tensors represents the shape of the output sparse
        ///    tensors.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    For example, if the input is
        ///    
        ///    input_tensor = shape = [2, 7]
        ///    [    a   d e  ]
        ///    [b c          ]
        ///    
        ///    Graphically the output tensors are:
        ///    
        ///    sparse_slice([0, 0], [2, 4]) = shape = [2, 4]
        ///    [    a  ]
        ///    [b c    ]
        ///    
        ///    sparse_slice([0, 4], [2, 3]) = shape = [2, 3]
        ///    [ d e  ]
        ///    [      ]
        /// </remarks>
        public static (Tensor output_indices, Tensor output_values, Tensor output_shape) sparse_slice (Tensor indices, Tensor values, Tensor shape, Tensor start, Tensor size, string name = "SparseSlice")
        {
            var dict = new Dictionary<string, object>();
            dict["indices"] = indices;
            dict["values"] = values;
            dict["shape"] = shape;
            dict["start"] = start;
            dict["size"] = size;
            var op = _op_def_lib._apply_op_helper("SparseSlice", name: name, keywords: dict);
            int _idx = 0;
            var output_indices = op.outputs[_idx++];
            var output_values = op.outputs[_idx++];
            var output_shape = op.outputs[_idx++];
            return (output_indices, output_values, output_shape);
        }

        /// <summary>
        ///    The gradient operator for the SparseSlice op.
        /// </summary>
        /// <param name="backprop_val_grad">
        ///    1-D. The gradient with respect to
        ///    the non-empty values of the sliced <c>SparseTensor</c>.
        /// </param>
        /// <param name="input_indices">
        ///    2-D.  The <c>indices</c> of the input <c>SparseTensor</c>.
        /// </param>
        /// <param name="input_start">
        ///    1-D. tensor represents the start of the slice.
        /// </param>
        /// <param name="output_indices">
        ///    2-D.  The <c>indices</c> of the sliced <c>SparseTensor</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseSliceGrad'.
        /// </param>
        /// <returns>
        ///    1-D. The gradient with respect to the non-empty values of input <c>SparseTensor</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op takes in the upstream gradient w.r.t. non-empty values of
        ///    the sliced <c>SparseTensor</c>, and outputs the gradients w.r.t.
        ///    the non-empty values of input <c>SparseTensor</c>.
        /// </remarks>
        public static Tensor sparse_slice_grad (Tensor backprop_val_grad, Tensor input_indices, Tensor input_start, Tensor output_indices, string name = "SparseSliceGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["backprop_val_grad"] = backprop_val_grad;
            dict["input_indices"] = input_indices;
            dict["input_start"] = input_start;
            dict["output_indices"] = output_indices;
            var op = _op_def_lib._apply_op_helper("SparseSliceGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Applies softmax to a batched N-D <c>SparseTensor</c>.
        /// </summary>
        /// <param name="sp_indices">
        ///    2-D.  <c>NNZ x R</c> matrix with the indices of non-empty values in a
        ///    SparseTensor, in canonical ordering.
        /// </param>
        /// <param name="sp_values">
        ///    1-D.  <c>NNZ</c> non-empty values corresponding to <c>sp_indices</c>.
        /// </param>
        /// <param name="sp_shape">
        ///    1-D.  Shape of the input SparseTensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseSoftmax'.
        /// </param>
        /// <returns>
        ///    1-D.  The <c>NNZ</c> values for the result <c>SparseTensor</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The inputs represent an N-D SparseTensor  with logical shape <c>[..., B, C]</c>
        ///    (where <c>N &amp;gt;= 2</c>), and with indices sorted in the canonical lexicographic order.
        ///    
        ///    This op is equivalent to applying the normal <c>tf.nn.softmax()</c> to each innermost
        ///    logical submatrix with shape <c>[B, C]</c>, but with the catch that *the implicitly
        ///    zero elements do not participate*.  Specifically, the algorithm is equivalent
        ///    to the following:
        ///    
        ///    (1) Applies <c>tf.nn.softmax()</c> to a densified view of each innermost submatrix
        ///    with shape <c>[B, C]</c>, along the size-C dimension;
        ///    (2) Masks out the original implicitly-zero locations;
        ///    (3) Renormalizes the remaining elements.
        ///    
        ///    Hence, the <c>SparseTensor</c> result has exactly the same non-zero indices and
        ///    shape.
        /// </remarks>
        public static Tensor sparse_softmax (Tensor sp_indices, Tensor sp_values, Tensor sp_shape, string name = "SparseSoftmax")
        {
            var dict = new Dictionary<string, object>();
            dict["sp_indices"] = sp_indices;
            dict["sp_values"] = sp_values;
            dict["sp_shape"] = sp_shape;
            var op = _op_def_lib._apply_op_helper("SparseSoftmax", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes softmax cross entropy cost and gradients to backpropagate.
        /// </summary>
        /// <param name="features">
        ///    batch_size x num_classes matrix
        /// </param>
        /// <param name="labels">
        ///    batch_size vector with values in [0, num_classes).
        ///    This is the label for the given minibatch entry.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseSoftmaxCrossEntropyWithLogits'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    loss : Per example loss (batch_size vector).
        ///    backprop : backpropagated gradients (batch_size x num_classes matrix).
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Unlike <c>SoftmaxCrossEntropyWithLogits</c>, this operation does not accept
        ///    a matrix of label probabilities, but rather a single label per row
        ///    of features.  This label is considered to have probability 1.0 for the
        ///    given row.
        ///    
        ///    Inputs are the logits, not probabilities.
        /// </remarks>
        public static (Tensor loss, Tensor backprop) sparse_softmax_cross_entropy_with_logits (Tensor features, Tensor labels, string name = "SparseSoftmaxCrossEntropyWithLogits")
        {
            var dict = new Dictionary<string, object>();
            dict["features"] = features;
            dict["labels"] = labels;
            var op = _op_def_lib._apply_op_helper("SparseSoftmaxCrossEntropyWithLogits", name: name, keywords: dict);
            int _idx = 0;
            var loss = op.outputs[_idx++];
            var backprop = op.outputs[_idx++];
            return (loss, backprop);
        }

        /// <summary>
        ///    Returns the element-wise max of two SparseTensors.
        /// </summary>
        /// <param name="a_indices">
        ///    2-D.  <c>N x R</c> matrix with the indices of non-empty values in a
        ///    SparseTensor, in the canonical lexicographic ordering.
        /// </param>
        /// <param name="a_values">
        ///    1-D.  <c>N</c> non-empty values corresponding to <c>a_indices</c>.
        /// </param>
        /// <param name="a_shape">
        ///    1-D.  Shape of the input SparseTensor.
        /// </param>
        /// <param name="b_indices">
        ///    counterpart to <c>a_indices</c> for the other operand.
        /// </param>
        /// <param name="b_values">
        ///    counterpart to <c>a_values</c> for the other operand; must be of the same dtype.
        /// </param>
        /// <param name="b_shape">
        ///    counterpart to <c>a_shape</c> for the other operand; the two shapes must be equal.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseSparseMaximum'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output_indices : 2-D.  The indices of the output SparseTensor.
        ///    output_values : 1-D.  The values of the output SparseTensor.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Assumes the two SparseTensors have the same shape, i.e., no broadcasting.
        /// </remarks>
        public static (Tensor output_indices, Tensor output_values) sparse_sparse_maximum (Tensor a_indices, Tensor a_values, Tensor a_shape, Tensor b_indices, Tensor b_values, Tensor b_shape, string name = "SparseSparseMaximum")
        {
            var dict = new Dictionary<string, object>();
            dict["a_indices"] = a_indices;
            dict["a_values"] = a_values;
            dict["a_shape"] = a_shape;
            dict["b_indices"] = b_indices;
            dict["b_values"] = b_values;
            dict["b_shape"] = b_shape;
            var op = _op_def_lib._apply_op_helper("SparseSparseMaximum", name: name, keywords: dict);
            int _idx = 0;
            var output_indices = op.outputs[_idx++];
            var output_values = op.outputs[_idx++];
            return (output_indices, output_values);
        }

        /// <summary>
        ///    Returns the element-wise min of two SparseTensors.
        /// </summary>
        /// <param name="a_indices">
        ///    2-D.  <c>N x R</c> matrix with the indices of non-empty values in a
        ///    SparseTensor, in the canonical lexicographic ordering.
        /// </param>
        /// <param name="a_values">
        ///    1-D.  <c>N</c> non-empty values corresponding to <c>a_indices</c>.
        /// </param>
        /// <param name="a_shape">
        ///    1-D.  Shape of the input SparseTensor.
        /// </param>
        /// <param name="b_indices">
        ///    counterpart to <c>a_indices</c> for the other operand.
        /// </param>
        /// <param name="b_values">
        ///    counterpart to <c>a_values</c> for the other operand; must be of the same dtype.
        /// </param>
        /// <param name="b_shape">
        ///    counterpart to <c>a_shape</c> for the other operand; the two shapes must be equal.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseSparseMinimum'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output_indices : 2-D.  The indices of the output SparseTensor.
        ///    output_values : 1-D.  The values of the output SparseTensor.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Assumes the two SparseTensors have the same shape, i.e., no broadcasting.
        /// </remarks>
        public static (Tensor output_indices, Tensor output_values) sparse_sparse_minimum (Tensor a_indices, Tensor a_values, Tensor a_shape, Tensor b_indices, Tensor b_values, Tensor b_shape, string name = "SparseSparseMinimum")
        {
            var dict = new Dictionary<string, object>();
            dict["a_indices"] = a_indices;
            dict["a_values"] = a_values;
            dict["a_shape"] = a_shape;
            dict["b_indices"] = b_indices;
            dict["b_values"] = b_values;
            dict["b_shape"] = b_shape;
            var op = _op_def_lib._apply_op_helper("SparseSparseMinimum", name: name, keywords: dict);
            int _idx = 0;
            var output_indices = op.outputs[_idx++];
            var output_values = op.outputs[_idx++];
            return (output_indices, output_values);
        }

        /// <summary>
        ///    Split a <c>SparseTensor</c> into <c>num_split</c> tensors along one dimension.
        /// </summary>
        /// <param name="split_dim">
        ///    0-D.  The dimension along which to split.  Must be in the range
        ///    <c>[0, rank(shape))</c>.
        /// </param>
        /// <param name="indices">
        ///    2-D tensor represents the indices of the sparse tensor.
        /// </param>
        /// <param name="values">
        ///    1-D tensor represents the values of the sparse tensor.
        /// </param>
        /// <param name="shape">
        ///    1-D. tensor represents the shape of the sparse tensor.
        ///    output indices: A list of 1-D tensors represents the indices of the output
        ///    sparse tensors.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseSplit'.
        /// </param>
        /// <param name="num_split">
        ///    Optional argument
        ///    The number of ways to split.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output_indices :
        ///    output_values : A list of 1-D tensors represents the values of the output sparse
        ///    tensors.
        ///    output_shape : A list of 1-D tensors represents the shape of the output sparse
        ///    tensors.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    If the <c>shape[split_dim]</c> is not an integer multiple of <c>num_split</c>. Slices
        ///    <c>[0 : shape[split_dim] % num_split]</c> gets one extra dimension.
        ///    For example, if <c>split_dim = 1</c> and <c>num_split = 2</c> and the input is
        ///    
        ///    input_tensor = shape = [2, 7]
        ///    [    a   d e  ]
        ///    [b c          ]
        ///    
        ///    Graphically the output tensors are:
        ///    
        ///    output_tensor[0] = shape = [2, 4]
        ///    [    a  ]
        ///    [b c    ]
        ///    
        ///    output_tensor[1] = shape = [2, 3]
        ///    [ d e  ]
        ///    [      ]
        /// </remarks>
        public static (Tensor[] output_indices, Tensor[] output_values, Tensor[] output_shape) sparse_split (Tensor split_dim, Tensor indices, Tensor values, Tensor shape, int num_split, string name = "SparseSplit")
        {
            var dict = new Dictionary<string, object>();
            dict["split_dim"] = split_dim;
            dict["indices"] = indices;
            dict["values"] = values;
            dict["shape"] = shape;
            dict["num_split"] = num_split;
            var op = _op_def_lib._apply_op_helper("SparseSplit", name: name, keywords: dict);
            int _idx = 0;
            var output_indices = Enumerable.Range(0, op.OutputListLength("output_indices")).Select(_ => op.outputs[_idx++]).ToArray();
            var output_values = Enumerable.Range(0, op.OutputListLength("output_values")).Select(_ => op.outputs[_idx++]).ToArray();
            var output_shape = Enumerable.Range(0, op.OutputListLength("output_shape")).Select(_ => op.outputs[_idx++]).ToArray();
            return (output_indices, output_values, output_shape);
        }

        /// <summary>
        ///    Adds up a <c>SparseTensor</c> and a dense <c>Tensor</c>, producing a dense <c>Tensor</c>.
        /// </summary>
        /// <param name="a_indices">
        ///    2-D.  The <c>indices</c> of the <c>SparseTensor</c>, with shape <c>[nnz, ndims]</c>.
        /// </param>
        /// <param name="a_values">
        ///    1-D.  The <c>values</c> of the <c>SparseTensor</c>, with shape <c>[nnz]</c>.
        /// </param>
        /// <param name="a_shape">
        ///    1-D.  The <c>shape</c> of the <c>SparseTensor</c>, with shape <c>[ndims]</c>.
        /// </param>
        /// <param name="b">
        ///    <c>ndims</c>-D Tensor.  With shape <c>a_shape</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseTensorDenseAdd'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This Op does not require <c>a_indices</c> be sorted in standard lexicographic order.
        /// </remarks>
        public static Tensor sparse_tensor_dense_add (Tensor a_indices, Tensor a_values, Tensor a_shape, Tensor b, string name = "SparseTensorDenseAdd")
        {
            var dict = new Dictionary<string, object>();
            dict["a_indices"] = a_indices;
            dict["a_values"] = a_values;
            dict["a_shape"] = a_shape;
            dict["b"] = b;
            var op = _op_def_lib._apply_op_helper("SparseTensorDenseAdd", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Multiply SparseTensor (of rank 2) "A" by dense matrix "B".
        /// </summary>
        /// <param name="a_indices">
        ///    2-D.  The <c>indices</c> of the <c>SparseTensor</c>, size <c>[nnz, 2]</c> Matrix.
        /// </param>
        /// <param name="a_values">
        ///    1-D.  The <c>values</c> of the <c>SparseTensor</c>, size <c>[nnz]</c> Vector.
        /// </param>
        /// <param name="a_shape">
        ///    1-D.  The <c>shape</c> of the <c>SparseTensor</c>, size <c>[2]</c> Vector.
        /// </param>
        /// <param name="b">
        ///    2-D.  A dense Matrix.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseTensorDenseMatMul'.
        /// </param>
        /// <param name="adjoint_a">
        ///    Use the adjoint of A in the matrix multiply.  If A is complex, this
        ///    is transpose(conj(A)).  Otherwise it's transpose(A).
        /// </param>
        /// <param name="adjoint_b">
        ///    Use the adjoint of B in the matrix multiply.  If B is complex, this
        ///    is transpose(conj(B)).  Otherwise it's transpose(B).
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    No validity checking is performed on the indices of A.  However, the following
        ///    input format is recommended for optimal behavior:
        ///    
        ///    if adjoint_a == false:
        ///    A should be sorted in lexicographically increasing order.  Use SparseReorder
        ///    if you're not sure.
        ///    if adjoint_a == true:
        ///    A should be sorted in order of increasing dimension 1 (i.e., "column major"
        ///    order instead of "row major" order).
        /// </remarks>
        public static Tensor sparse_tensor_dense_mat_mul (Tensor a_indices, Tensor a_values, Tensor a_shape, Tensor b, bool? adjoint_a = null, bool? adjoint_b = null, string name = "SparseTensorDenseMatMul")
        {
            var dict = new Dictionary<string, object>();
            dict["a_indices"] = a_indices;
            dict["a_values"] = a_values;
            dict["a_shape"] = a_shape;
            dict["b"] = b;
            if (adjoint_a.HasValue)
                dict["adjoint_a"] = adjoint_a.Value;
            if (adjoint_b.HasValue)
                dict["adjoint_b"] = adjoint_b.Value;
            var op = _op_def_lib._apply_op_helper("SparseTensorDenseMatMul", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a dataset that splits a SparseTensor into elements row-wise.
        /// </summary>
        /// <param name="indices">
        /// </param>
        /// <param name="values">
        /// </param>
        /// <param name="dense_shape">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseTensorSliceDataset'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor sparse_tensor_slice_dataset (Tensor indices, Tensor values, Tensor dense_shape, string name = "SparseTensorSliceDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["indices"] = indices;
            dict["values"] = values;
            dict["dense_shape"] = dense_shape;
            var op = _op_def_lib._apply_op_helper("SparseTensorSliceDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Converts a sparse representation into a dense tensor.
        /// </summary>
        /// <param name="sparse_indices">
        ///    0-D, 1-D, or 2-D.  <c>sparse_indices[i]</c> contains the complete
        ///    index where <c>sparse_values[i]</c> will be placed.
        /// </param>
        /// <param name="output_shape">
        ///    1-D.  Shape of the dense output tensor.
        /// </param>
        /// <param name="sparse_values">
        ///    1-D.  Values corresponding to each row of <c>sparse_indices</c>,
        ///    or a scalar value to be used for all sparse indices.
        /// </param>
        /// <param name="default_value">
        ///    Scalar value to set for indices not specified in
        ///    <c>sparse_indices</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseToDense'.
        /// </param>
        /// <param name="validate_indices">
        ///    If true, indices are checked to make sure they are sorted in
        ///    lexicographic order and that there are no repeats.
        /// </param>
        /// <returns>
        ///    Dense output tensor of shape <c>output_shape</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Builds an array <c>dense</c> with shape <c>output_shape</c> such that
        ///    
        ///   <code>
        ///    # If sparse_indices is scalar
        ///    dense[i] = (i == sparse_indices ? sparse_values : default_value)
        ///    
        ///    # If sparse_indices is a vector, then for each i
        ///    dense[sparse_indices[i]] = sparse_values[i]
        ///    
        ///    # If sparse_indices is an n by d matrix, then for each i in [0, n)
        ///    dense[sparse_indices[i][0], ..., sparse_indices[i][d-1]] = sparse_values[i]
        ///   </code>
        ///    
        ///    All other values in <c>dense</c> are set to <c>default_value</c>.  If <c>sparse_values</c> is a
        ///    scalar, all sparse indices are set to this single value.
        ///    
        ///    Indices should be sorted in lexicographic order, and indices must not
        ///    contain any repeats. If <c>validate_indices</c> is true, these properties
        ///    are checked during execution.
        /// </remarks>
        public static Tensor sparse_to_dense (Tensor sparse_indices, Tensor output_shape, Tensor sparse_values, Tensor default_value, bool? validate_indices = null, string name = "SparseToDense")
        {
            var dict = new Dictionary<string, object>();
            dict["sparse_indices"] = sparse_indices;
            dict["output_shape"] = output_shape;
            dict["sparse_values"] = sparse_values;
            dict["default_value"] = default_value;
            if (validate_indices.HasValue)
                dict["validate_indices"] = validate_indices.Value;
            var op = _op_def_lib._apply_op_helper("SparseToDense", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Applies set operation along last dimension of 2 <c>SparseTensor</c> inputs.
        /// </summary>
        /// <param name="set1_indices">
        ///    2D <c>Tensor</c>, indices of a <c>SparseTensor</c>. Must be in row-major
        ///    order.
        /// </param>
        /// <param name="set1_values">
        ///    1D <c>Tensor</c>, values of a <c>SparseTensor</c>. Must be in row-major
        ///    order.
        /// </param>
        /// <param name="set1_shape">
        ///    1D <c>Tensor</c>, shape of a <c>SparseTensor</c>. <c>set1_shape[0...n-1]</c> must
        ///    be the same as <c>set2_shape[0...n-1]</c>, <c>set1_shape[n]</c> is the
        ///    max set size across <c>0...n-1</c> dimensions.
        /// </param>
        /// <param name="set2_indices">
        ///    2D <c>Tensor</c>, indices of a <c>SparseTensor</c>. Must be in row-major
        ///    order.
        /// </param>
        /// <param name="set2_values">
        ///    1D <c>Tensor</c>, values of a <c>SparseTensor</c>. Must be in row-major
        ///    order.
        /// </param>
        /// <param name="set2_shape">
        ///    1D <c>Tensor</c>, shape of a <c>SparseTensor</c>. <c>set2_shape[0...n-1]</c> must
        ///    be the same as <c>set1_shape[0...n-1]</c>, <c>set2_shape[n]</c> is the
        ///    max set size across <c>0...n-1</c> dimensions.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SparseToSparseSetOperation'.
        /// </param>
        /// <param name="set_operation">
        ///    Optional argument
        /// </param>
        /// <param name="validate_indices">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    result_indices : 2D indices of a <c>SparseTensor</c>.
        ///    result_values : 1D values of a <c>SparseTensor</c>.
        ///    result_shape : 1D <c>Tensor</c> shape of a <c>SparseTensor</c>. <c>result_shape[0...n-1]</c> is
        ///    the same as the 1st <c>n-1</c> dimensions of <c>set1</c> and <c>set2</c>, <c>result_shape[n]</c>
        ///    is the max result set size across all <c>0...n-1</c> dimensions.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    See SetOperationOp::SetOperationFromContext for values of <c>set_operation</c>.
        ///    
        ///    If <c>validate_indices</c> is <c>True</c>, <c>SparseToSparseSetOperation</c> validates the
        ///    order and range of <c>set1</c> and <c>set2</c> indices.
        ///    
        ///    Input <c>set1</c> is a <c>SparseTensor</c> represented by <c>set1_indices</c>, <c>set1_values</c>,
        ///    and <c>set1_shape</c>. For <c>set1</c> ranked <c>n</c>, 1st <c>n-1</c> dimensions must be the same
        ///    as <c>set2</c>. Dimension <c>n</c> contains values in a set, duplicates are allowed but
        ///    ignored.
        ///    
        ///    Input <c>set2</c> is a <c>SparseTensor</c> represented by <c>set2_indices</c>, <c>set2_values</c>,
        ///    and <c>set2_shape</c>. For <c>set2</c> ranked <c>n</c>, 1st <c>n-1</c> dimensions must be the same
        ///    as <c>set1</c>. Dimension <c>n</c> contains values in a set, duplicates are allowed but
        ///    ignored.
        ///    
        ///    If <c>validate_indices</c> is <c>True</c>, this op validates the order and range of <c>set1</c>
        ///    and <c>set2</c> indices.
        ///    
        ///    Output <c>result</c> is a <c>SparseTensor</c> represented by <c>result_indices</c>,
        ///    <c>result_values</c>, and <c>result_shape</c>. For <c>set1</c> and <c>set2</c> ranked <c>n</c>, this
        ///    has rank <c>n</c> and the same 1st <c>n-1</c> dimensions as <c>set1</c> and <c>set2</c>. The <c>nth</c>
        ///    dimension contains the result of <c>set_operation</c> applied to the corresponding
        ///    <c>[0...n-1]</c> dimension of <c>set</c>.
        /// </remarks>
        public static (Tensor result_indices, Tensor result_values, Tensor result_shape) sparse_to_sparse_set_operation (Tensor set1_indices, Tensor set1_values, Tensor set1_shape, Tensor set2_indices, Tensor set2_values, Tensor set2_shape, string set_operation, bool? validate_indices = null, string name = "SparseToSparseSetOperation")
        {
            var dict = new Dictionary<string, object>();
            dict["set1_indices"] = set1_indices;
            dict["set1_values"] = set1_values;
            dict["set1_shape"] = set1_shape;
            dict["set2_indices"] = set2_indices;
            dict["set2_values"] = set2_values;
            dict["set2_shape"] = set2_shape;
            dict["set_operation"] = set_operation;
            if (validate_indices.HasValue)
                dict["validate_indices"] = validate_indices.Value;
            var op = _op_def_lib._apply_op_helper("SparseToSparseSetOperation", name: name, keywords: dict);
            int _idx = 0;
            var result_indices = op.outputs[_idx++];
            var result_values = op.outputs[_idx++];
            var result_shape = op.outputs[_idx++];
            return (result_indices, result_values, result_shape);
        }

        /// <summary>
        ///    Splits a tensor into <c>num_split</c> tensors along one dimension.
        /// </summary>
        /// <param name="split_dim">
        ///    0-D.  The dimension along which to split.  Must be in the range
        ///    <c>[-rank(value), rank(value))</c>.
        /// </param>
        /// <param name="value">
        ///    The tensor to split.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Split'.
        /// </param>
        /// <param name="num_split">
        ///    Optional argument
        ///    The number of ways to split.  Must evenly divide
        ///    <c>value.shape[split_dim]</c>.
        /// </param>
        /// <returns>
        ///    They are identically shaped tensors, whose shape matches that of <c>value</c>
        ///    except along <c>axis</c>, where their sizes are
        ///    <c>values.shape[split_dim] / num_split</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor[] split (Tensor split_dim, Tensor value, int num_split, string name = "Split")
        {
            var dict = new Dictionary<string, object>();
            dict["split_dim"] = split_dim;
            dict["value"] = value;
            dict["num_split"] = num_split;
            var op = _op_def_lib._apply_op_helper("Split", name: name, keywords: dict);
            int _idx = 0;
            var output = Enumerable.Range(0, op.OutputListLength("output")).Select(_ => op.outputs[_idx++]).ToArray();
            return (output);
        }

        /// <summary>
        ///    Splits a tensor into <c>num_split</c> tensors along one dimension.
        /// </summary>
        /// <param name="value">
        ///    The tensor to split.
        /// </param>
        /// <param name="size_splits">
        ///    list containing the sizes of each output tensor along the split
        ///    dimension. Must sum to the dimension of value along split_dim.
        ///    Can contain one -1 indicating that dimension is to be inferred.
        /// </param>
        /// <param name="split_dim">
        ///    0-D.  The dimension along which to split.  Must be in the range
        ///    <c>[-rank(value), rank(value))</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SplitV'.
        /// </param>
        /// <param name="num_split">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    Tensors whose shape matches that of <c>value</c>
        ///    except along <c>axis</c>, where their sizes are
        ///    <c>size_splits[i]</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor[] split_v (Tensor value, Tensor size_splits, Tensor split_dim, int num_split, string name = "SplitV")
        {
            var dict = new Dictionary<string, object>();
            dict["value"] = value;
            dict["size_splits"] = size_splits;
            dict["split_dim"] = split_dim;
            dict["num_split"] = num_split;
            var op = _op_def_lib._apply_op_helper("SplitV", name: name, keywords: dict);
            int _idx = 0;
            var output = Enumerable.Range(0, op.OutputListLength("output")).Select(_ => op.outputs[_idx++]).ToArray();
            return (output);
        }

        /// <summary>
        ///    Creates a dataset that executes a SQL query and emits rows of the result set.
        /// </summary>
        /// <param name="driver_name">
        ///    The database type. Currently, the only supported type is 'sqlite'.
        /// </param>
        /// <param name="data_source_name">
        ///    A connection string to connect to the database.
        /// </param>
        /// <param name="query">
        ///    A SQL query to execute.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SqlDataset'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor sql_dataset (Tensor driver_name, Tensor data_source_name, Tensor query, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "SqlDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["driver_name"] = driver_name;
            dict["data_source_name"] = data_source_name;
            dict["query"] = query;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("SqlDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes square root of x element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Sqrt'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    I.e., \\(y = \sqrt{x} = x^{1/2}\\).
        /// </remarks>
        public static Tensor sqrt (Tensor x, string name = "Sqrt")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Sqrt", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradient for the sqrt of <c>x</c> wrt its input.
        /// </summary>
        /// <param name="y">
        /// </param>
        /// <param name="dy">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SqrtGrad'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Specifically, <c>grad = dy * 0.5 / y</c>, where <c>y = sqrt(x)</c>, and <c>dy</c>
        ///    is the corresponding input gradient.
        /// </remarks>
        public static Tensor sqrt_grad (Tensor y, Tensor dy, string name = "SqrtGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["y"] = y;
            dict["dy"] = dy;
            var op = _op_def_lib._apply_op_helper("SqrtGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes square of x element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Square'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    I.e., \\(y = x * x = x^2\\).
        /// </remarks>
        public static Tensor square (Tensor x, string name = "Square")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Square", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns (x - y)(x - y) element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'SquaredDifference'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    *NOTE*: <c>SquaredDifference</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor squared_difference (Tensor x, Tensor y, string name = "SquaredDifference")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("SquaredDifference", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Removes dimensions of size 1 from the shape of a tensor.
        /// </summary>
        /// <param name="input">
        ///    The <c>input</c> to squeeze.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Squeeze'.
        /// </param>
        /// <param name="squeeze_dims">
        ///    If specified, only squeezes the dimensions listed. The dimension
        ///    index starts at 0. It is an error to squeeze a dimension that is not 1. Must
        ///    be in the range <c>[-rank(input), rank(input))</c>.
        /// </param>
        /// <returns>
        ///    Contains the same data as <c>input</c>, but has one or more dimensions of
        ///    size 1 removed.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Given a tensor <c>input</c>, this operation returns a tensor of the same type with
        ///    all dimensions of size 1 removed. If you don't want to remove all size 1
        ///    dimensions, you can remove specific size 1 dimensions by specifying
        ///    <c>axis</c>.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # 't' is a tensor of shape [1, 2, 1, 3, 1, 1]
        ///    shape(squeeze(t)) ==&amp;gt; [2, 3]
        ///   </code>
        ///    
        ///    Or, to remove specific size 1 dimensions:
        ///    
        ///   <code>
        ///    # 't' is a tensor of shape [1, 2, 1, 3, 1, 1]
        ///    shape(squeeze(t, [2, 4])) ==&amp;gt; [1, 2, 3, 1]
        ///   </code>
        /// </remarks>
        public static Tensor squeeze (Tensor input, int[] squeeze_dims = null, string name = "Squeeze")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (squeeze_dims != null)
                dict["squeeze_dims"] = squeeze_dims;
            var op = _op_def_lib._apply_op_helper("Squeeze", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Deprecated, use StackV2.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Stack'.
        /// </param>
        /// <param name="elem_type">
        ///    Optional argument
        /// </param>
        /// <param name="stack_name">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor stack (TF_DataType elem_type, string stack_name = null, string name = "Stack")
        {
            var dict = new Dictionary<string, object>();
            dict["elem_type"] = elem_type;
            if (stack_name != null)
                dict["stack_name"] = stack_name;
            var op = _op_def_lib._apply_op_helper("Stack", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Deprecated, use StackCloseV2.
        /// </summary>
        /// <param name="handle">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StackClose'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation stack_close (Tensor handle, string name = "StackClose")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            var op = _op_def_lib._apply_op_helper("StackClose", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Delete the stack from its resource container.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a stack.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StackCloseV2'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation stack_close_v2 (Tensor handle, string name = "StackCloseV2")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            var op = _op_def_lib._apply_op_helper("StackCloseV2", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Deprecated, use StackPopV2.
        /// </summary>
        /// <param name="handle">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StackPop'.
        /// </param>
        /// <param name="elem_type">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor stack_pop (Tensor handle, TF_DataType elem_type, string name = "StackPop")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["elem_type"] = elem_type;
            var op = _op_def_lib._apply_op_helper("StackPop", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Pop the element at the top of the stack.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a stack.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StackPopV2'.
        /// </param>
        /// <param name="elem_type">
        ///    Optional argument
        ///    The type of the elem that is popped.
        /// </param>
        /// <returns>
        ///    The tensor that is popped from the top of the stack.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor stack_pop_v2 (Tensor handle, TF_DataType elem_type, string name = "StackPopV2")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["elem_type"] = elem_type;
            var op = _op_def_lib._apply_op_helper("StackPopV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Deprecated, use StackPushV2.
        /// </summary>
        /// <param name="handle">
        /// </param>
        /// <param name="elem">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StackPush'.
        /// </param>
        /// <param name="swap_memory">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor stack_push (Tensor handle, Tensor elem, bool? swap_memory = null, string name = "StackPush")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["elem"] = elem;
            if (swap_memory.HasValue)
                dict["swap_memory"] = swap_memory.Value;
            var op = _op_def_lib._apply_op_helper("StackPush", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Push an element onto the stack.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a stack.
        /// </param>
        /// <param name="elem">
        ///    The tensor to be pushed onto the stack.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StackPushV2'.
        /// </param>
        /// <param name="swap_memory">
        ///    Swap <c>elem</c> to CPU. Default to false.
        /// </param>
        /// <returns>
        ///    The same tensor as the input 'elem'.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor stack_push_v2 (Tensor handle, Tensor elem, bool? swap_memory = null, string name = "StackPushV2")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["elem"] = elem;
            if (swap_memory.HasValue)
                dict["swap_memory"] = swap_memory.Value;
            var op = _op_def_lib._apply_op_helper("StackPushV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A stack that produces elements in first-in last-out order.
        /// </summary>
        /// <param name="max_size">
        ///    The maximum size of the stack if non-negative. If negative, the stack
        ///    size is unlimited.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StackV2'.
        /// </param>
        /// <param name="elem_type">
        ///    Optional argument
        ///    The type of the elements on the stack.
        /// </param>
        /// <param name="stack_name">
        ///    Overrides the name used for the temporary stack resource. Default
        ///    value is the name of the 'Stack' op (which is guaranteed unique).
        /// </param>
        /// <returns>
        ///    The handle to the stack.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor stack_v2 (Tensor max_size, TF_DataType elem_type, string stack_name = null, string name = "StackV2")
        {
            var dict = new Dictionary<string, object>();
            dict["max_size"] = max_size;
            dict["elem_type"] = elem_type;
            if (stack_name != null)
                dict["stack_name"] = stack_name;
            var op = _op_def_lib._apply_op_helper("StackV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Stage values similar to a lightweight Enqueue.
        /// </summary>
        /// <param name="values">
        ///    a list of tensors
        ///    dtypes A list of data types that inserted values should adhere to.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Stage'.
        /// </param>
        /// <param name="capacity">
        ///    Maximum number of elements in the Staging Area. If &amp;gt; 0, inserts
        ///    on the container will block when the capacity is reached.
        /// </param>
        /// <param name="memory_limit">
        ///    The maximum number of bytes allowed for Tensors in the Staging Area.
        ///    If &amp;gt; 0, inserts will block until sufficient space is available.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this queue is placed in the given container. Otherwise,
        ///    a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    It is necessary to match this name to the matching Unstage Op.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    The basic functionality of this Op is similar to a queue with many
        ///    fewer capabilities and options.  This Op is optimized for performance.
        /// </remarks>
        public static Operation stage (Tensor[] values, int? capacity = null, int? memory_limit = null, string container = null, string shared_name = null, string name = "Stage")
        {
            var dict = new Dictionary<string, object>();
            dict["values"] = values;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (memory_limit.HasValue)
                dict["memory_limit"] = memory_limit.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("Stage", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Op removes all elements in the underlying container.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StageClear'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        /// </param>
        /// <param name="capacity">
        /// </param>
        /// <param name="memory_limit">
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation stage_clear (TF_DataType[] dtypes, int? capacity = null, int? memory_limit = null, string container = null, string shared_name = null, string name = "StageClear")
        {
            var dict = new Dictionary<string, object>();
            dict["dtypes"] = dtypes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (memory_limit.HasValue)
                dict["memory_limit"] = memory_limit.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("StageClear", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Op peeks at the values at the specified index.  If the
        /// </summary>
        /// <param name="index">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StagePeek'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        /// </param>
        /// <param name="capacity">
        /// </param>
        /// <param name="memory_limit">
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    underlying container does not contain sufficient elements
        ///    this op will block until it does.   This Op is optimized for
        ///    performance.
        /// </remarks>
        public static Tensor[] stage_peek (Tensor index, TF_DataType[] dtypes, int? capacity = null, int? memory_limit = null, string container = null, string shared_name = null, string name = "StagePeek")
        {
            var dict = new Dictionary<string, object>();
            dict["index"] = index;
            dict["dtypes"] = dtypes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (memory_limit.HasValue)
                dict["memory_limit"] = memory_limit.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("StagePeek", name: name, keywords: dict);
            int _idx = 0;
            var values = Enumerable.Range(0, op.OutputListLength("values")).Select(_ => op.outputs[_idx++]).ToArray();
            return (values);
        }

        /// <summary>
        ///    Op returns the number of elements in the underlying container.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StageSize'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        /// </param>
        /// <param name="capacity">
        /// </param>
        /// <param name="memory_limit">
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor stage_size (TF_DataType[] dtypes, int? capacity = null, int? memory_limit = null, string container = null, string shared_name = null, string name = "StageSize")
        {
            var dict = new Dictionary<string, object>();
            dict["dtypes"] = dtypes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (memory_limit.HasValue)
                dict["memory_limit"] = memory_limit.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("StageSize", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Draws samples from a multinomial distribution.
        /// </summary>
        /// <param name="logits">
        ///    2-D Tensor with shape <c>[batch_size, num_classes]</c>.  Each slice <c>[i, :]</c>
        ///    represents the unnormalized log probabilities for all classes.
        /// </param>
        /// <param name="num_samples">
        ///    0-D.  Number of independent samples to draw for each row slice.
        /// </param>
        /// <param name="seed">
        ///    2 seeds (shape [2]).
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StatelessMultinomial'.
        /// </param>
        /// <param name="output_dtype">
        /// </param>
        /// <returns>
        ///    2-D Tensor with shape <c>[batch_size, num_samples]</c>.  Each slice <c>[i, :]</c>
        ///    contains the drawn class labels with range <c>[0, num_classes)</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor stateless_multinomial (Tensor logits, Tensor num_samples, Tensor seed, TF_DataType? output_dtype = null, string name = "StatelessMultinomial")
        {
            var dict = new Dictionary<string, object>();
            dict["logits"] = logits;
            dict["num_samples"] = num_samples;
            dict["seed"] = seed;
            if (output_dtype.HasValue)
                dict["output_dtype"] = output_dtype.Value;
            var op = _op_def_lib._apply_op_helper("StatelessMultinomial", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Outputs deterministic pseudorandom values from a normal distribution.
        /// </summary>
        /// <param name="shape">
        ///    The shape of the output tensor.
        /// </param>
        /// <param name="seed">
        ///    2 seeds (shape [2]).
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StatelessRandomNormal'.
        /// </param>
        /// <param name="dtype">
        ///    The type of the output.
        /// </param>
        /// <returns>
        ///    Random values with specified shape.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The generated values will have mean 0 and standard deviation 1.
        ///    
        ///    The outputs are a deterministic function of <c>shape</c> and <c>seed</c>.
        /// </remarks>
        public static Tensor stateless_random_normal (Tensor shape, Tensor seed, TF_DataType? dtype = null, string name = "StatelessRandomNormal")
        {
            var dict = new Dictionary<string, object>();
            dict["shape"] = shape;
            dict["seed"] = seed;
            if (dtype.HasValue)
                dict["dtype"] = dtype.Value;
            var op = _op_def_lib._apply_op_helper("StatelessRandomNormal", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Outputs deterministic pseudorandom random values from a uniform distribution.
        /// </summary>
        /// <param name="shape">
        ///    The shape of the output tensor.
        /// </param>
        /// <param name="seed">
        ///    2 seeds (shape [2]).
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StatelessRandomUniform'.
        /// </param>
        /// <param name="dtype">
        ///    The type of the output.
        /// </param>
        /// <returns>
        ///    Random values with specified shape.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The generated values follow a uniform distribution in the range <c>[0, 1)</c>. The
        ///    lower bound 0 is included in the range, while the upper bound 1 is excluded.
        ///    
        ///    The outputs are a deterministic function of <c>shape</c> and <c>seed</c>.
        /// </remarks>
        public static Tensor stateless_random_uniform (Tensor shape, Tensor seed, TF_DataType? dtype = null, string name = "StatelessRandomUniform")
        {
            var dict = new Dictionary<string, object>();
            dict["shape"] = shape;
            dict["seed"] = seed;
            if (dtype.HasValue)
                dict["dtype"] = dtype.Value;
            var op = _op_def_lib._apply_op_helper("StatelessRandomUniform", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Outputs deterministic pseudorandom values from a truncated normal distribution.
        /// </summary>
        /// <param name="shape">
        ///    The shape of the output tensor.
        /// </param>
        /// <param name="seed">
        ///    2 seeds (shape [2]).
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StatelessTruncatedNormal'.
        /// </param>
        /// <param name="dtype">
        ///    The type of the output.
        /// </param>
        /// <returns>
        ///    Random values with specified shape.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The generated values follow a normal distribution with mean 0 and standard
        ///    deviation 1, except that values whose magnitude is more than 2 standard
        ///    deviations from the mean are dropped and re-picked.
        ///    
        ///    The outputs are a deterministic function of <c>shape</c> and <c>seed</c>.
        /// </remarks>
        public static Tensor stateless_truncated_normal (Tensor shape, Tensor seed, TF_DataType? dtype = null, string name = "StatelessTruncatedNormal")
        {
            var dict = new Dictionary<string, object>();
            dict["shape"] = shape;
            dict["seed"] = seed;
            if (dtype.HasValue)
                dict["dtype"] = dtype.Value;
            var op = _op_def_lib._apply_op_helper("StatelessTruncatedNormal", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Replaces the match of pattern in input with rewrite.
        /// </summary>
        /// <param name="input">
        ///    The text to be processed.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StaticRegexReplace'.
        /// </param>
        /// <param name="pattern">
        ///    Optional argument
        ///    The regular expression to match the input.
        /// </param>
        /// <param name="rewrite">
        ///    Optional argument
        ///    The rewrite to be applied to the matched expresion.
        /// </param>
        /// <param name="replace_global">
        ///    If True, the replacement is global, otherwise the replacement
        ///    is done only on the first match.
        /// </param>
        /// <returns>
        ///    The text after applying pattern and rewrite.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    It follows the re2 syntax (https://github.com/google/re2/wiki/Syntax)
        /// </remarks>
        public static Tensor static_regex_replace (Tensor input, string pattern, string rewrite, bool? replace_global = null, string name = "StaticRegexReplace")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["pattern"] = pattern;
            dict["rewrite"] = rewrite;
            if (replace_global.HasValue)
                dict["replace_global"] = replace_global.Value;
            var op = _op_def_lib._apply_op_helper("StaticRegexReplace", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a statistics manager resource.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StatsAggregatorHandle'.
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor stats_aggregator_handle (string container = null, string shared_name = null, string name = "StatsAggregatorHandle")
        {
            var dict = new Dictionary<string, object>();
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("StatsAggregatorHandle", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Produces a summary of any statistics recorded by the given statistics manager.
        /// </summary>
        /// <param name="iterator">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StatsAggregatorSummary'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor stats_aggregator_summary (Tensor iterator, string name = "StatsAggregatorSummary")
        {
            var dict = new Dictionary<string, object>();
            dict["iterator"] = iterator;
            var op = _op_def_lib._apply_op_helper("StatsAggregatorSummary", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Stops gradient computation.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StopGradient'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    When executed in a graph, this op outputs its input tensor as-is.
        ///    
        ///    When building ops to compute gradients, this op prevents the contribution of
        ///    its inputs to be taken into account.  Normally, the gradient generator adds ops
        ///    to a graph to compute the derivatives of a specified 'loss' by recursively
        ///    finding out inputs that contributed to its computation.  If you insert this op
        ///    in the graph it inputs are masked from the gradient generator.  They are not
        ///    taken into account for computing gradients.
        ///    
        ///    This is useful any time you want to compute a value with TensorFlow but need
        ///    to pretend that the value was a constant. Some examples include:
        ///    
        ///    *  The *EM* algorithm where the *M-step* should not involve backpropagation
        ///    through the output of the *E-step*.
        ///    *  Contrastive divergence training of Boltzmann machines where, when
        ///    differentiating the energy function, the training must not backpropagate
        ///    through the graph that generated the samples from the model.
        ///    *  Adversarial training, where no backprop should happen through the adversarial
        ///    example generation process.
        /// </remarks>
        public static Tensor stop_gradient (Tensor input, string name = "StopGradient")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("StopGradient", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Return a strided slice from <c>input</c>.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="begin">
        ///    <c>begin[k]</c> specifies the offset into the <c>k</c>th range specification.
        ///    The exact dimension this corresponds to will be determined by context.
        ///    Out-of-bounds values will be silently clamped. If the <c>k</c>th bit of
        ///    <c>begin_mask</c> then <c>begin[k]</c> is ignored and the full range of the
        ///    appropriate dimension is used instead. Negative values causes indexing
        ///    to start from the highest element e.g. If <c>foo==[1,2,3]</c> then <c>foo[-1]==3</c>.
        /// </param>
        /// <param name="end">
        ///    <c>end[i]</c> is like <c>begin</c> with the exception that <c>end_mask</c> is
        ///    used to determine full ranges.
        /// </param>
        /// <param name="strides">
        ///    <c>strides[i]</c> specifies the increment in the <c>i</c>th specification
        ///    after extracting a given element. Negative indices will reverse
        ///    the original order. Out or range values are
        ///    clamped to <c>[0,dim[i]) if slice[i]&amp;gt;0</c> or <c>[-1,dim[i]-1] if slice[i] &amp;lt; 0</c>
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StridedSlice'.
        /// </param>
        /// <param name="begin_mask">
        ///    a bitmask where a bit i being 1 means to ignore the begin
        ///    value and instead use the largest interval possible. At runtime
        ///    begin[i] will be replaced with <c>[0, n-1)</c> if <c>stride[i] &amp;gt; 0</c> or
        ///    <c>[-1, n-1]</c> if <c>stride[i] &amp;lt; 0</c>
        /// </param>
        /// <param name="end_mask">
        ///    analogous to <c>begin_mask</c>
        /// </param>
        /// <param name="ellipsis_mask">
        ///    a bitmask where bit <c>i</c> being 1 means the <c>i</c>th
        ///    position is actually an ellipsis. One bit at most can be 1.
        ///    If <c>ellipsis_mask == 0</c>, then an implicit ellipsis mask of <c>1 &amp;lt;&amp;lt; (m+1)</c>
        ///    is provided. This means that <c>foo[3:5] == foo[3:5, ...]</c>. An ellipsis
        ///    implicitly creates as many range specifications as necessary to fully
        ///    specify the sliced range for every dimension. For example for a 4-dimensional
        ///    tensor <c>foo</c> the slice <c>foo[2, ..., 5:8]</c> implies <c>foo[2, :, :, 5:8]</c>.
        /// </param>
        /// <param name="new_axis_mask">
        ///    a bitmask where bit <c>i</c> being 1 means the <c>i</c>th
        ///    specification creates a new shape 1 dimension. For example
        ///    <c>foo[:4, tf.newaxis, :2]</c> would produce a shape <c>(4, 1, 2)</c> tensor.
        /// </param>
        /// <param name="shrink_axis_mask">
        ///    a bitmask where bit <c>i</c> implies that the <c>i</c>th
        ///    specification should shrink the dimensionality. begin and end
        ///    must imply a slice of size 1 in the dimension. For example in
        ///    python one might do <c>foo[:, 3, :]</c> which would result in
        ///    <c>shrink_axis_mask</c> being 2.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Note, most python users will want to use the Python <c>Tensor.__getitem__</c>
        ///    or <c>Variable.__getitem__</c> rather than this op directly.
        ///    
        ///    The goal of this op is to produce a new tensor with a subset of
        ///    the elements from the <c>n</c> dimensional <c>input</c> tensor. The subset is chosen using
        ///    a sequence of <c>m</c> sparse range specifications encoded into the arguments
        ///    of this function. Note, in some cases
        ///    <c>m</c> could be equal to <c>n</c>, but this need not be the case. Each
        ///    range specification entry can be one of the following:
        ///    
        ///    - An ellipsis (...). Ellipses are used to imply zero or more
        ///    dimensions of full-dimension selection and are produced using
        ///    <c>ellipsis_mask</c>. For example, <c>foo[...]</c> is the identity slice.
        ///    
        ///    - A new axis. This is used to insert a new shape=1 dimension and is
        ///    produced using <c>new_axis_mask</c>. For example, <c>foo[:, ...]</c> where
        ///    <c>foo</c> is shape <c>(3, 4)</c> produces a <c>(1, 3, 4)</c> tensor.
        ///    
        ///    
        ///    - A range <c>begin:end:stride</c>. This is used to specify how much to choose from
        ///    a given dimension. <c>stride</c> can be any integer but 0.  <c>begin</c> is an integer
        ///    which represents the index of the first value to select while <c>end</c> represents
        ///    the index of the last value to select. The number of values selected in each
        ///    dimension is <c>end - begin</c> if <c>stride &amp;gt; 0</c> and <c>begin - end</c> if <c>stride &amp;lt; 0</c>.
        ///    <c>begin</c> and <c>end</c> can be negative where <c>-1</c> is the last element, <c>-2</c> is
        ///    the second to last. <c>begin_mask</c> controls whether to replace the explicitly
        ///    given <c>begin</c> with an implicit effective value of <c>0</c> if <c>stride &amp;gt; 0</c> and
        ///    <c>-1</c> if <c>stride &amp;lt; 0</c>. <c>end_mask</c> is analogous but produces the number
        ///    required to create the largest open interval. For example, given a shape
        ///    <c>(3,)</c> tensor <c>foo[:]</c>, the effective <c>begin</c> and <c>end</c> are <c>0</c> and <c>3</c>. Do
        ///    not assume this is equivalent to <c>foo[0:-1]</c> which has an effective <c>begin</c>
        ///    and <c>end</c> of <c>0</c> and <c>2</c>. Another example is <c>foo[-2::-1]</c> which reverses the
        ///    first dimension of a tensor while dropping the last two (in the original
        ///    order elements). For example <c>foo = [1,2,3,4]; foo[-2::-1]</c> is <c>[4,3]</c>.
        ///    
        ///    - A single index. This is used to keep only elements that have a given
        ///    index. For example (<c>foo[2, :]</c> on a shape <c>(5,6)</c> tensor produces a
        ///    shape <c>(6,)</c> tensor. This is encoded in <c>begin</c> and <c>end</c> and
        ///    <c>shrink_axis_mask</c>.
        ///    
        ///    Each conceptual range specification is encoded in the op's argument. This
        ///    encoding is best understand by considering a non-trivial example. In
        ///    particular,
        ///    <c>foo[1, 2:4, None, ..., :-3:-1, :]</c> will be encoded as
        ///    
        ///   <code>
        ///    begin = [1, 2, x, x, 0, x] # x denotes don't care (usually 0)
        ///    end = [2, 4, x, x, -3, x]
        ///    strides = [1, 1, x, x, -1, 1]
        ///    begin_mask = 1&amp;lt;&amp;lt;4 | 1 &amp;lt;&amp;lt; 5 = 48
        ///    end_mask = 1&amp;lt;&amp;lt;5 = 32
        ///    ellipsis_mask = 1&amp;lt;&amp;lt;3 = 8
        ///    new_axis_mask = 1&amp;lt;&amp;lt;2 4
        ///    shrink_axis_mask = 1&amp;lt;&amp;lt;0
        ///   </code>
        ///    
        ///    In this case if <c>foo.shape</c> is (5, 5, 5, 5, 5, 5) the final shape of
        ///    the slice becomes (2, 1, 5, 5, 2, 5).
        ///    Let us walk step by step through each argument specification.
        ///    
        ///    1.  The first argument in the example slice is turned into <c>begin = 1</c> and
        ///    <c>end = begin + 1 = 2</c>. To disambiguate from the original spec <c>2:4</c> we
        ///    also set the appropriate bit in <c>shrink_axis_mask</c>.
        ///    
        ///    2. <c>2:4</c> is contributes 2, 4, 1 to begin, end, and stride. All masks have
        ///    zero bits contributed.
        ///    
        ///    3. None is a synonym for <c>tf.newaxis</c>. This means insert a dimension of size 1
        ///    dimension in the final shape. Dummy values are contributed to begin,
        ///    end and stride, while the new_axis_mask bit is set.
        ///    
        ///    4. <c>...</c> grab the full ranges from as many dimensions as needed to
        ///    fully specify a slice for every dimension of the input shape.
        ///    
        ///    5. <c>:-3:-1</c> shows the use of negative indices. A negative index <c>i</c> associated
        ///    with a dimension that has shape <c>s</c> is converted to a positive index
        ///    <c>s + i</c>. So <c>-1</c> becomes <c>s-1</c> (i.e. the last element). This conversion
        ///    is done internally so begin, end and strides receive x, -3, and -1.
        ///    The appropriate begin_mask bit is set to indicate the start range is the
        ///    full range (ignoring the x).
        ///    
        ///    6. <c>:</c> indicates that the entire contents of the corresponding dimension
        ///    is selected. This is equivalent to <c>::</c> or <c>0::1</c>. begin, end, and strides
        ///    receive 0, 0, and 1, respectively. The appropriate bits in <c>begin_mask</c> and
        ///    <c>end_mask</c> are also set.
        ///    
        ///    *Requirements*:
        ///    <c>0 != strides[i] for i in [0, m)</c>
        ///    <c>ellipsis_mask must be a power of two (only one ellipsis)</c>
        /// </remarks>
        public static Tensor strided_slice (Tensor input, Tensor begin, Tensor end, Tensor strides, int? begin_mask = null, int? end_mask = null, int? ellipsis_mask = null, int? new_axis_mask = null, int? shrink_axis_mask = null, string name = "StridedSlice")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["begin"] = begin;
            dict["end"] = end;
            dict["strides"] = strides;
            if (begin_mask.HasValue)
                dict["begin_mask"] = begin_mask.Value;
            if (end_mask.HasValue)
                dict["end_mask"] = end_mask.Value;
            if (ellipsis_mask.HasValue)
                dict["ellipsis_mask"] = ellipsis_mask.Value;
            if (new_axis_mask.HasValue)
                dict["new_axis_mask"] = new_axis_mask.Value;
            if (shrink_axis_mask.HasValue)
                dict["shrink_axis_mask"] = shrink_axis_mask.Value;
            var op = _op_def_lib._apply_op_helper("StridedSlice", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Assign <c>value</c> to the sliced l-value reference of <c>ref</c>.
        /// </summary>
        /// <param name="referecne">
        /// </param>
        /// <param name="begin">
        /// </param>
        /// <param name="end">
        /// </param>
        /// <param name="strides">
        /// </param>
        /// <param name="value">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StridedSliceAssign'.
        /// </param>
        /// <param name="begin_mask">
        /// </param>
        /// <param name="end_mask">
        /// </param>
        /// <param name="ellipsis_mask">
        /// </param>
        /// <param name="new_axis_mask">
        /// </param>
        /// <param name="shrink_axis_mask">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The values of <c>value</c> are assigned to the positions in the variable
        ///    <c>ref</c> that are selected by the slice parameters. The slice parameters
        ///    <c>begin, </c>end<c>, </c>strides<c>, etc. work exactly as in </c>StridedSlice<c>.
        ///    
        ///    NOTE this op currently does not support broadcasting and so </c>value<c>'s
        ///    shape must be exactly the shape produced by the slice of </c>ref<c>.
        /// </remarks>
        public static Tensor strided_slice_assign (Tensor referecne, Tensor begin, Tensor end, Tensor strides, Tensor value, int? begin_mask = null, int? end_mask = null, int? ellipsis_mask = null, int? new_axis_mask = null, int? shrink_axis_mask = null, string name = "StridedSliceAssign")
        {
            var dict = new Dictionary<string, object>();
            dict["ref"] = referecne;
            dict["begin"] = begin;
            dict["end"] = end;
            dict["strides"] = strides;
            dict["value"] = value;
            if (begin_mask.HasValue)
                dict["begin_mask"] = begin_mask.Value;
            if (end_mask.HasValue)
                dict["end_mask"] = end_mask.Value;
            if (ellipsis_mask.HasValue)
                dict["ellipsis_mask"] = ellipsis_mask.Value;
            if (new_axis_mask.HasValue)
                dict["new_axis_mask"] = new_axis_mask.Value;
            if (shrink_axis_mask.HasValue)
                dict["shrink_axis_mask"] = shrink_axis_mask.Value;
            var op = _op_def_lib._apply_op_helper("StridedSliceAssign", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the gradient of <c>StridedSlice</c>.
        /// </summary>
        /// <param name="shape">
        /// </param>
        /// <param name="begin">
        /// </param>
        /// <param name="end">
        /// </param>
        /// <param name="strides">
        /// </param>
        /// <param name="dy">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StridedSliceGrad'.
        /// </param>
        /// <param name="begin_mask">
        /// </param>
        /// <param name="end_mask">
        /// </param>
        /// <param name="ellipsis_mask">
        /// </param>
        /// <param name="new_axis_mask">
        /// </param>
        /// <param name="shrink_axis_mask">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Since <c>StridedSlice</c> cuts out pieces of its <c>input</c> which is size
        ///    <c>shape</c>, its gradient will have the same shape (which is passed here
        ///    as <c>shape</c>). The gradient will be zero in any element that the slice
        ///    does not select.
        ///    
        ///    Arguments are the same as StridedSliceGrad with the exception that
        ///    <c>dy</c> is the input gradient to be propagated and <c>shape</c> is the
        ///    shape of <c>StridedSlice</c>'s <c>input</c>.
        /// </remarks>
        public static Tensor strided_slice_grad (Tensor shape, Tensor begin, Tensor end, Tensor strides, Tensor dy, int? begin_mask = null, int? end_mask = null, int? ellipsis_mask = null, int? new_axis_mask = null, int? shrink_axis_mask = null, string name = "StridedSliceGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["shape"] = shape;
            dict["begin"] = begin;
            dict["end"] = end;
            dict["strides"] = strides;
            dict["dy"] = dy;
            if (begin_mask.HasValue)
                dict["begin_mask"] = begin_mask.Value;
            if (end_mask.HasValue)
                dict["end_mask"] = end_mask.Value;
            if (ellipsis_mask.HasValue)
                dict["ellipsis_mask"] = ellipsis_mask.Value;
            if (new_axis_mask.HasValue)
                dict["new_axis_mask"] = new_axis_mask.Value;
            if (shrink_axis_mask.HasValue)
                dict["shrink_axis_mask"] = shrink_axis_mask.Value;
            var op = _op_def_lib._apply_op_helper("StridedSliceGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Joins the strings in the given list of string tensors into one tensor;
        /// </summary>
        /// <param name="inputs">
        ///    A list of string tensors.  The tensors must all have the same shape,
        ///    or be scalars.  Scalars may be mixed in; these will be broadcast to the shape
        ///    of non-scalar inputs.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StringJoin'.
        /// </param>
        /// <param name="separator">
        ///    string, an optional join separator.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    with the given separator (default is an empty separator).
        /// </remarks>
        public static Tensor string_join (Tensor[] inputs, string separator = null, string name = "StringJoin")
        {
            var dict = new Dictionary<string, object>();
            dict["inputs"] = inputs;
            if (separator != null)
                dict["separator"] = separator;
            var op = _op_def_lib._apply_op_helper("StringJoin", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Split elements of <c>input</c> based on <c>delimiter</c> into a <c>SparseTensor</c>.
        /// </summary>
        /// <param name="input">
        ///    1-D. Strings to split.
        /// </param>
        /// <param name="delimiter">
        ///    0-D. Delimiter characters (bytes), or empty string.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StringSplit'.
        /// </param>
        /// <param name="skip_empty">
        ///    A <c>bool</c>. If <c>True</c>, skip the empty strings from the result.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    indices : A dense matrix of int64 representing the indices of the sparse tensor.
        ///    values : A vector of strings corresponding to the splited values.
        ///    shape : a length-2 vector of int64 representing the shape of the sparse
        ///    tensor, where the first value is N and the second value is the maximum number
        ///    of tokens in a single input entry.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Let N be the size of source (typically N will be the batch size). Split each
        ///    element of <c>input</c> based on <c>delimiter</c> and return a <c>SparseTensor</c>
        ///    containing the splitted tokens. Empty tokens are ignored.
        ///    
        ///    <c>delimiter</c> can be empty, or a string of split characters. If <c>delimiter</c> is an
        ///    empty string, each element of <c>input</c> is split into individual single-byte
        ///    character strings, including splitting of UTF-8 multibyte sequences. Otherwise
        ///    every character of <c>delimiter</c> is a potential split point.
        ///    
        ///    For example:
        ///    N = 2, input[0] is 'hello world' and input[1] is 'a b c', then the output
        ///    will be
        ///    
        ///    indices = [0, 0;
        ///    0, 1;
        ///    1, 0;
        ///    1, 1;
        ///    1, 2]
        ///    shape = [2, 3]
        ///    values = ['hello', 'world', 'a', 'b', 'c']
        /// </remarks>
        public static (Tensor indices, Tensor values, Tensor shape) string_split (Tensor input, Tensor delimiter, bool? skip_empty = null, string name = "StringSplit")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["delimiter"] = delimiter;
            if (skip_empty.HasValue)
                dict["skip_empty"] = skip_empty.Value;
            var op = _op_def_lib._apply_op_helper("StringSplit", name: name, keywords: dict);
            int _idx = 0;
            var indices = op.outputs[_idx++];
            var values = op.outputs[_idx++];
            var shape = op.outputs[_idx++];
            return (indices, values, shape);
        }

        /// <summary>
        ///    Split elements of <c>source</c> based on <c>sep</c> into a <c>SparseTensor</c>.
        /// </summary>
        /// <param name="input">
        ///    <c>1-D</c> string <c>Tensor</c>, the strings to split.
        /// </param>
        /// <param name="sep">
        ///    <c>0-D</c> string <c>Tensor</c>, the delimiter character.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StringSplitV2'.
        /// </param>
        /// <param name="maxsplit">
        ///    An <c>int</c>. If <c>maxsplit &amp;gt; 0</c>, limit of the split of the result.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    indices :
        ///    values :
        ///    shape :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Let N be the size of source (typically N will be the batch size). Split each
        ///    element of <c>source</c> based on <c>sep</c> and return a <c>SparseTensor</c>
        ///    containing the split tokens. Empty tokens are ignored.
        ///    
        ///    For example, N = 2, source[0] is 'hello world' and source[1] is 'a b c',
        ///    then the output will be
        ///   <code>
        ///    st.indices = [0, 0;
        ///    0, 1;
        ///    1, 0;
        ///    1, 1;
        ///    1, 2]
        ///    st.shape = [2, 3]
        ///    st.values = ['hello', 'world', 'a', 'b', 'c']
        ///   </code>
        ///    
        ///    If <c>sep</c> is given, consecutive delimiters are not grouped together and are
        ///    deemed to delimit empty strings. For example, source of <c>"1&amp;lt;&amp;gt;2&amp;lt;&amp;gt;&amp;lt;&amp;gt;3"</c> and
        ///    sep of <c>"&amp;lt;&amp;gt;"</c> returns <c>["1", "2", "", "3"]</c>. If <c>sep</c> is None or an empty
        ///    string, consecutive whitespace are regarded as a single separator, and the
        ///    result will contain no empty strings at the startor end if the string has
        ///    leading or trailing whitespace.
        ///    
        ///    Note that the above mentioned behavior matches python's str.split.
        /// </remarks>
        public static (Tensor indices, Tensor values, Tensor shape) string_split_v2 (Tensor input, Tensor sep, int? maxsplit = null, string name = "StringSplitV2")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["sep"] = sep;
            if (maxsplit.HasValue)
                dict["maxsplit"] = maxsplit.Value;
            var op = _op_def_lib._apply_op_helper("StringSplitV2", name: name, keywords: dict);
            int _idx = 0;
            var indices = op.outputs[_idx++];
            var values = op.outputs[_idx++];
            var shape = op.outputs[_idx++];
            return (indices, values, shape);
        }

        /// <summary>
        ///    Strip leading and trailing whitespaces from the Tensor.
        /// </summary>
        /// <param name="input">
        ///    A string <c>Tensor</c> of any shape.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StringStrip'.
        /// </param>
        /// <returns>
        ///    A string <c>Tensor</c> of the same shape as the input.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor string_strip (Tensor input, string name = "StringStrip")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("StringStrip", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Converts each string in the input Tensor to its hash mod by a number of buckets.
        /// </summary>
        /// <param name="string_tensor">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StringToHashBucket'.
        /// </param>
        /// <param name="num_buckets">
        ///    Optional argument
        ///    The number of buckets.
        /// </param>
        /// <returns>
        ///    A Tensor of the same shape as the input <c>string_tensor</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The hash function is deterministic on the content of the string within the
        ///    process.
        ///    
        ///    Note that the hash function may change from time to time.
        ///    This functionality will be deprecated and it's recommended to use
        ///    <c>tf.string_to_hash_bucket_fast()</c> or <c>tf.string_to_hash_bucket_strong()</c>.
        /// </remarks>
        public static Tensor string_to_hash_bucket (Tensor string_tensor, int num_buckets, string name = "StringToHashBucket")
        {
            var dict = new Dictionary<string, object>();
            dict["string_tensor"] = string_tensor;
            dict["num_buckets"] = num_buckets;
            var op = _op_def_lib._apply_op_helper("StringToHashBucket", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Converts each string in the input Tensor to its hash mod by a number of buckets.
        /// </summary>
        /// <param name="input">
        ///    The strings to assign a hash bucket.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StringToHashBucketFast'.
        /// </param>
        /// <param name="num_buckets">
        ///    Optional argument
        ///    The number of buckets.
        /// </param>
        /// <returns>
        ///    A Tensor of the same shape as the input <c>string_tensor</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The hash function is deterministic on the content of the string within the
        ///    process and will never change. However, it is not suitable for cryptography.
        ///    This function may be used when CPU time is scarce and inputs are trusted or
        ///    unimportant. There is a risk of adversaries constructing inputs that all hash
        ///    to the same bucket. To prevent this problem, use a strong hash function with
        ///    <c>tf.string_to_hash_bucket_strong</c>.
        /// </remarks>
        public static Tensor string_to_hash_bucket_fast (Tensor input, int num_buckets, string name = "StringToHashBucketFast")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["num_buckets"] = num_buckets;
            var op = _op_def_lib._apply_op_helper("StringToHashBucketFast", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Converts each string in the input Tensor to its hash mod by a number of buckets.
        /// </summary>
        /// <param name="input">
        ///    The strings to assign a hash bucket.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StringToHashBucketStrong'.
        /// </param>
        /// <param name="num_buckets">
        ///    Optional argument
        ///    The number of buckets.
        /// </param>
        /// <param name="key">
        ///    Optional argument
        ///    The key for the keyed hash function passed as a list of two uint64
        ///    elements.
        /// </param>
        /// <returns>
        ///    A Tensor of the same shape as the input <c>string_tensor</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The hash function is deterministic on the content of the string within the
        ///    process. The hash function is a keyed hash function, where attribute <c>key</c>
        ///    defines the key of the hash function. <c>key</c> is an array of 2 elements.
        ///    
        ///    A strong hash is important when inputs may be malicious, e.g. URLs with
        ///    additional components. Adversaries could try to make their inputs hash to the
        ///    same bucket for a denial-of-service attack or to skew the results. A strong
        ///    hash prevents this by making it difficult, if not infeasible, to compute inputs
        ///    that hash to the same bucket. This comes at a cost of roughly 4x higher compute
        ///    time than <c>tf.string_to_hash_bucket_fast</c>.
        /// </remarks>
        public static Tensor string_to_hash_bucket_strong (Tensor input, int num_buckets, int[] key, string name = "StringToHashBucketStrong")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["num_buckets"] = num_buckets;
            dict["key"] = key;
            var op = _op_def_lib._apply_op_helper("StringToHashBucketStrong", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Converts each string in the input Tensor to the specified numeric type.
        /// </summary>
        /// <param name="string_tensor">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'StringToNumber'.
        /// </param>
        /// <param name="out_type">
        ///    The numeric type to interpret each string in <c>string_tensor</c> as.
        /// </param>
        /// <returns>
        ///    A Tensor of the same shape as the input <c>string_tensor</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    (Note that int32 overflow results in an error while float overflow
        ///    results in a rounded value.)
        /// </remarks>
        public static Tensor string_to_number (Tensor string_tensor, TF_DataType? out_type = null, string name = "StringToNumber")
        {
            var dict = new Dictionary<string, object>();
            dict["string_tensor"] = string_tensor;
            if (out_type.HasValue)
                dict["out_type"] = out_type.Value;
            var op = _op_def_lib._apply_op_helper("StringToNumber", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns x - y element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Sub'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    *NOTE*: <c>Subtract</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor sub (Tensor x, Tensor y, string name = "Sub")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("Sub", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Return substrings from <c>Tensor</c> of strings.
        /// </summary>
        /// <param name="input">
        ///    Tensor of strings
        /// </param>
        /// <param name="pos">
        ///    Scalar defining the position of first character in each substring
        /// </param>
        /// <param name="len">
        ///    Scalar defining the number of characters to include in each substring
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Substr'.
        /// </param>
        /// <returns>
        ///    Tensor of substrings
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    For each string in the input <c>Tensor</c>, creates a substring starting at index
        ///    <c>pos</c> with a total length of <c>len</c>.
        ///    
        ///    If <c>len</c> defines a substring that would extend beyond the length of the input
        ///    string, then as many characters as possible are used.
        ///    
        ///    A negative <c>pos</c> indicates distance within the string backwards from the end.
        ///    
        ///    If <c>pos</c> specifies an index which is out of range for any of the input strings,
        ///    then an <c>InvalidArgumentError</c> is thrown.
        ///    
        ///    <c>pos</c> and <c>len</c> must have the same shape, otherwise a <c>ValueError</c> is thrown on
        ///    Op creation.
        ///    
        ///    *NOTE*: <c>Substr</c> supports broadcasting up to two dimensions. More about
        ///    broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        ///    
        ///    ---
        ///    
        ///    Examples
        ///    
        ///    Using scalar <c>pos</c> and <c>len</c>:
        ///    
        ///   <code>
        ///    input = [b'Hello', b'World']
        ///    position = 1
        ///    length = 3
        ///    
        ///    output = [b'ell', b'orl']
        ///   </code>
        ///    
        ///    Using <c>pos</c> and <c>len</c> with same shape as <c>input</c>:
        ///    
        ///   <code>
        ///    input = [[b'ten', b'eleven', b'twelve'],
        ///    [b'thirteen', b'fourteen', b'fifteen'],
        ///    [b'sixteen', b'seventeen', b'eighteen']]
        ///    position = [[1, 2, 3],
        ///    [1, 2, 3],
        ///    [1, 2, 3]]
        ///    length =   [[2, 3, 4],
        ///    [4, 3, 2],
        ///    [5, 5, 5]]
        ///    
        ///    output = [[b'en', b'eve', b'lve'],
        ///    [b'hirt', b'urt', b'te'],
        ///    [b'ixtee', b'vente', b'hteen']]
        ///   </code>
        ///    
        ///    Broadcasting <c>pos</c> and <c>len</c> onto <c>input</c>:
        ///    
        ///   <code>
        ///    input = [[b'ten', b'eleven', b'twelve'],
        ///    [b'thirteen', b'fourteen', b'fifteen'],
        ///    [b'sixteen', b'seventeen', b'eighteen'],
        ///    [b'nineteen', b'twenty', b'twentyone']]
        ///    position = [1, 2, 3]
        ///    length =   [1, 2, 3]
        ///    
        ///    output = [[b'e', b'ev', b'lve'],
        ///    [b'h', b'ur', b'tee'],
        ///    [b'i', b've', b'hte'],
        ///    [b'i', b'en', b'nty']]
        ///   </code>
        ///    
        ///    Broadcasting <c>input</c> onto <c>pos</c> and <c>len</c>:
        ///    
        ///   <code>
        ///    input = b'thirteen'
        ///    position = [1, 5, 7]
        ///    length =   [3, 2, 1]
        ///    
        ///    output = [b'hir', b'ee', b'n']
        ///   </code>
        /// </remarks>
        public static Tensor substr (Tensor input, Tensor pos, Tensor len, string name = "Substr")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["pos"] = pos;
            dict["len"] = len;
            var op = _op_def_lib._apply_op_helper("Substr", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the sum of elements across dimensions of a tensor.
        /// </summary>
        /// <param name="input">
        ///    The tensor to reduce.
        /// </param>
        /// <param name="reduction_indices">
        ///    The dimensions to reduce. Must be in the range
        ///    <c>[-rank(input), rank(input))</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Sum'.
        /// </param>
        /// <param name="keep_dims">
        ///    If true, retain reduced dimensions with length 1.
        /// </param>
        /// <returns>
        ///    The reduced tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Reduces <c>input</c> along the dimensions given in <c>axis</c>. Unless
        ///    <c>keep_dims</c> is true, the rank of the tensor is reduced by 1 for each entry in
        ///    <c>axis</c>. If <c>keep_dims</c> is true, the reduced dimensions are
        ///    retained with length 1.
        /// </remarks>
        public static Tensor sum (Tensor input, Tensor reduction_indices, bool? keep_dims = null, string name = "Sum")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["reduction_indices"] = reduction_indices;
            if (keep_dims.HasValue)
                dict["keep_dims"] = keep_dims.Value;
            var op = _op_def_lib._apply_op_helper("Sum", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the singular value decompositions of one or more matrices.
        /// </summary>
        /// <param name="input">
        ///    A tensor of shape <c>[..., M, N]</c> whose inner-most 2 dimensions
        ///    form matrices of size <c>[M, N]</c>. Let <c>P</c> be the minimum of <c>M</c> and <c>N</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Svd'.
        /// </param>
        /// <param name="compute_uv">
        ///    If true, left and right singular vectors will be
        ///    computed and returned in <c>u</c> and <c>v</c>, respectively.
        ///    If false, <c>u</c> and <c>v</c> are not set and should never referenced.
        /// </param>
        /// <param name="full_matrices">
        ///    If true, compute full-sized <c>u</c> and <c>v</c>. If false
        ///    (the default), compute only the leading <c>P</c> singular vectors.
        ///    Ignored if <c>compute_uv</c> is <c>False</c>.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    s : Singular values. Shape is <c>[..., P]</c>.
        ///    u : Left singular vectors. If <c>full_matrices</c> is <c>False</c> then shape is
        ///    <c>[..., M, P]</c>; if <c>full_matrices</c> is <c>True</c> then shape is
        ///    <c>[..., M, M]</c>. Undefined if <c>compute_uv</c> is <c>False</c>.
        ///    v : Left singular vectors. If <c>full_matrices</c> is <c>False</c> then shape is
        ///    <c>[..., N, P]</c>. If <c>full_matrices</c> is <c>True</c> then shape is <c>[..., N, N]</c>.
        ///    Undefined if <c>compute_uv</c> is false.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Computes the SVD of each inner matrix in <c>input</c> such that
        ///    <c>input[..., :, :] = u[..., :, :] * diag(s[..., :, :]) * transpose(v[..., :, :])</c>
        ///    
        ///   <code>
        ///    # a is a tensor containing a batch of matrices.
        ///    # s is a tensor of singular values for each matrix.
        ///    # u is the tensor containing of left singular vectors for each matrix.
        ///    # v is the tensor containing of right singular vectors for each matrix.
        ///    s, u, v = svd(a)
        ///    s, _, _ = svd(a, compute_uv=False)
        ///   </code>
        /// </remarks>
        public static (Tensor s, Tensor u, Tensor v) svd (Tensor input, bool? compute_uv = null, bool? full_matrices = null, string name = "Svd")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (compute_uv.HasValue)
                dict["compute_uv"] = compute_uv.Value;
            if (full_matrices.HasValue)
                dict["full_matrices"] = full_matrices.Value;
            var op = _op_def_lib._apply_op_helper("Svd", name: name, keywords: dict);
            int _idx = 0;
            var s = op.outputs[_idx++];
            var u = op.outputs[_idx++];
            var v = op.outputs[_idx++];
            return (s, u, v);
        }

        /// <summary>
        ///    Forwards <c>data</c> to the output port determined by <c>pred</c>.
        /// </summary>
        /// <param name="data">
        ///    The tensor to be forwarded to the appropriate output.
        /// </param>
        /// <param name="pred">
        ///    A scalar that specifies which output port will receive data.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Switch'.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output_false : If <c>pred</c> is false, data will be forwarded to this output.
        ///    output_true : If <c>pred</c> is true, data will be forwarded to this output.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    If <c>pred</c> is true, the <c>data</c> input is forwarded to <c>output_true</c>. Otherwise,
        ///    the data goes to <c>output_false</c>.
        ///    
        ///    See also <c>RefSwitch</c> and <c>Merge</c>.
        /// </remarks>
        public static (Tensor output_false, Tensor output_true) switch_ (Tensor data, Tensor pred, string name = "Switch")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            dict["pred"] = pred;
            var op = _op_def_lib._apply_op_helper("Switch", name: name, keywords: dict);
            int _idx = 0;
            var output_false = op.outputs[_idx++];
            var output_true = op.outputs[_idx++];
            return (output_false, output_true);
        }

        /// <summary>
        ///    Creates a dataset that emits the records from one or more TFRecord files.
        /// </summary>
        /// <param name="filenames">
        ///    A scalar or vector containing the name(s) of the file(s) to be
        ///    read.
        /// </param>
        /// <param name="compression_type">
        ///    A scalar containing either (i) the empty string (no
        ///    compression), (ii) "ZLIB", or (iii) "GZIP".
        /// </param>
        /// <param name="buffer_size">
        ///    A scalar representing the number of bytes to buffer. A value of
        ///    0 means no buffering will be performed.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TFRecordDataset'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor t_f_record_dataset (Tensor filenames, Tensor compression_type, Tensor buffer_size, string name = "TFRecordDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["filenames"] = filenames;
            dict["compression_type"] = compression_type;
            dict["buffer_size"] = buffer_size;
            var op = _op_def_lib._apply_op_helper("TFRecordDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A Reader that outputs the records from a TensorFlow Records file.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TFRecordReader'.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this reader is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this reader is named in the given bucket
        ///    with this shared_name. Otherwise, the node name is used instead.
        /// </param>
        /// <param name="compression_type">
        /// </param>
        /// <returns>
        ///    The handle to reference the Reader.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor t_f_record_reader (string container = null, string shared_name = null, string compression_type = null, string name = "TFRecordReader")
        {
            var dict = new Dictionary<string, object>();
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            if (compression_type != null)
                dict["compression_type"] = compression_type;
            var op = _op_def_lib._apply_op_helper("TFRecordReader", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A Reader that outputs the records from a TensorFlow Records file.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TFRecordReaderV2'.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this reader is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this reader is named in the given bucket
        ///    with this shared_name. Otherwise, the node name is used instead.
        /// </param>
        /// <param name="compression_type">
        /// </param>
        /// <returns>
        ///    The handle to reference the Reader.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor t_f_record_reader_v2 (string container = null, string shared_name = null, string compression_type = null, string name = "TFRecordReaderV2")
        {
            var dict = new Dictionary<string, object>();
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            if (compression_type != null)
                dict["compression_type"] = compression_type;
            var op = _op_def_lib._apply_op_helper("TFRecordReaderV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    An op enabling differentiation of TPU Embeddings.
        /// </summary>
        /// <param name="embedding_variable">
        ///    A trainable variable, enabling optimizers to find this op.
        /// </param>
        /// <param name="sliced_activations">
        ///    The embedding activations Tensor to return.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TPUEmbeddingActivations'.
        /// </param>
        /// <param name="table_id">
        ///    Optional argument
        ///    The id of the table in the embedding layer configuration from which
        ///    these activations were computed.
        /// </param>
        /// <param name="lookup_id">
        ///    Optional argument
        ///    Identifier of the set of embedding indices which produced these
        ///    activations.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op simply returns its first input, which is assumed to have been sliced
        ///    from the Tensors returned by TPUEmbeddingDequeueActivations. The presence of this
        ///    op, and its first argument being a trainable Variable, enables automatic
        ///    differentiation of graphs containing embeddings via the TPU Embedding Python
        ///    libraries.
        /// </remarks>
        public static Tensor t_p_u_embedding_activations (Tensor embedding_variable, Tensor sliced_activations, int table_id, int lookup_id, string name = "TPUEmbeddingActivations")
        {
            var dict = new Dictionary<string, object>();
            dict["embedding_variable"] = embedding_variable;
            dict["sliced_activations"] = sliced_activations;
            dict["table_id"] = table_id;
            dict["lookup_id"] = lookup_id;
            var op = _op_def_lib._apply_op_helper("TPUEmbeddingActivations", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    An op that feeds a batch of embedding indices and weights to the TPU.
        /// </summary>
        /// <param name="sample_indices">
        ///    A list of rank 1 Tensors specifying row indices of the COO
        ///    sparse matrix representing the embedding lookups for each table.
        /// </param>
        /// <param name="embedding_indices">
        ///    A list of rank 1 Tensors  specifying column indices of the
        ///    COO sparse matrix representing the embedding lookups for each table.
        /// </param>
        /// <param name="aggregation_weights">
        ///    A list of rank 1 Tensors specifying the nonzero values
        ///    of the COO sparse matrix representing the embedding lookups for each table.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TPUEmbeddingEnqueueSparseBatch'.
        /// </param>
        /// <param name="device_ordinal">
        ///    The TPU device to use. This should be -1 when the Op
        ///    is running on a TPU device, and &amp;gt;= 0 when the Op is running on the CPU
        ///    device.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    Embedding lookups are equivalent to sparse-dense matrix multiplications: the
        ///    sparse matrix contains nonzeros in column j in order to retrieve row j from the
        ///    embedding table.
        ///    
        ///    The three Tensor list arguments (sample_indices, embedding_indices, and
        ///    aggregation_weights) represent these sparse matrices in COO format. The Tensor
        ///    lists each have one entry for each embedding table specified in the model.
        ///    For the kth embedding table, the three Tensors at position k in the list
        ///    specify a COO-format sparse matrix. For the kth table, the row indices,
        ///    column indices, and nonzero values of the COO sparse matrix are specified by
        ///    sample_indices[k], embedding_indices[k], and aggregation_weights[k],
        ///    respectively. Entries must be sorted by row index, then by column index.
        ///    
        ///    There should be at most one TPUEmbeddingEnqueueSparseBatch op in a signle
        ///    training step per TPU shard.
        /// </remarks>
        public static Operation t_p_u_embedding_enqueue_sparse_batch (Tensor[] sample_indices, Tensor[] embedding_indices, Tensor[] aggregation_weights, int? device_ordinal = null, string name = "TPUEmbeddingEnqueueSparseBatch")
        {
            var dict = new Dictionary<string, object>();
            dict["sample_indices"] = sample_indices;
            dict["embedding_indices"] = embedding_indices;
            dict["aggregation_weights"] = aggregation_weights;
            if (device_ordinal.HasValue)
                dict["device_ordinal"] = device_ordinal.Value;
            var op = _op_def_lib._apply_op_helper("TPUEmbeddingEnqueueSparseBatch", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Load an embedding table shard into TensorNode memories for use with Adagrad.
        /// </summary>
        /// <param name="parameters">
        ///    The shard of the embedding table resident on the host executing this
        ///    op. For single-TPU models, this is the entire embedding table.
        /// </param>
        /// <param name="accumulators">
        ///    Shard of the Adagrad accumulators resident on the host executing
        ///    this op.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TPUEmbeddingLoadAdagradParameters'.
        /// </param>
        /// <param name="tpu_embedding_config">
        ///    Optional argument
        ///    Serialized TPUEmbeddingConfiguration proto.
        /// </param>
        /// <param name="table_id">
        ///    Optional argument
        ///    The id of the table specified in the embedding_config.
        /// </param>
        /// <param name="num_hosts">
        ///    Optional argument
        ///    The number of CPU hosts in the distributed training job.
        /// </param>
        /// <param name="host_id">
        ///    Optional argument
        ///    Which CPU host in the distributed training job will execute this op.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    TPU embeddings use dedicated per-optimizer Ops for loading and retrieving
        ///    trainable variables and optimizer state from TPU memory. This op enables
        ///    functionality equivalent to AdagradOptimizer.
        /// </remarks>
        public static Operation t_p_u_embedding_load_adagrad_parameters (Tensor parameters, Tensor accumulators, string tpu_embedding_config, int table_id, int num_hosts, int host_id, string name = "TPUEmbeddingLoadAdagradParameters")
        {
            var dict = new Dictionary<string, object>();
            dict["parameters"] = parameters;
            dict["accumulators"] = accumulators;
            dict["tpu_embedding_config"] = tpu_embedding_config;
            dict["table_id"] = table_id;
            dict["num_hosts"] = num_hosts;
            dict["host_id"] = host_id;
            var op = _op_def_lib._apply_op_helper("TPUEmbeddingLoadAdagradParameters", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Load an embedding table shard into TPU memory for use with GradientDescent.
        /// </summary>
        /// <param name="parameters">
        ///    The shard of the embedding table resident on the host executing this
        ///    op. For single-TPU models, this is the entire embedding table.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TPUEmbeddingLoadGradientDescentParameters'.
        /// </param>
        /// <param name="tpu_embedding_config">
        ///    Optional argument
        ///    Serialized TPUEmbeddingConfiguration proto.
        /// </param>
        /// <param name="table_id">
        ///    Optional argument
        ///    The id of the table specified in the tpu_embedding_config.
        /// </param>
        /// <param name="num_hosts">
        ///    Optional argument
        ///    The number of CPU hosts in the distributed training job.
        /// </param>
        /// <param name="host_id">
        ///    Optional argument
        ///    Which CPU host in the distributed training job will execute this op.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    TPU embeddings use dedicated per-optimizer Ops for loading and retrieving
        ///    trainable variables and optimizer state from TPU memory. This op enables
        ///    functionality equivalent to GradientDescentOptimizer.
        /// </remarks>
        public static Operation t_p_u_embedding_load_gradient_descent_parameters (Tensor parameters, string tpu_embedding_config, int table_id, int num_hosts, int host_id, string name = "TPUEmbeddingLoadGradientDescentParameters")
        {
            var dict = new Dictionary<string, object>();
            dict["parameters"] = parameters;
            dict["tpu_embedding_config"] = tpu_embedding_config;
            dict["table_id"] = table_id;
            dict["num_hosts"] = num_hosts;
            dict["host_id"] = host_id;
            var op = _op_def_lib._apply_op_helper("TPUEmbeddingLoadGradientDescentParameters", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    An op that receives embedding activations on the TPU.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TPUEmbeddingReceiveActivations'.
        /// </param>
        /// <param name="num_tables">
        ///    Optional argument
        ///    The number of output activation tensors, equal to the number of
        ///    embedding tables in the model.
        /// </param>
        /// <param name="tpu_embedding_config">
        ///    Optional argument
        ///    Serialized TPUEmbeddingConfiguration proto.
        /// </param>
        /// <returns>
        ///    A TensorList of embedding activations containing one Tensor per
        ///    embedding table in the model.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The TPU system performs the embedding lookups and aggregations specified by
        ///    the arguments to TPUEmbeddingEnqueueSparseBatch. The results of these
        ///    aggregations are visible to the Tensorflow Graph as the outputs of a
        ///    TPUEmbeddingDequeueActivations Op. This op returns a list containing one
        ///    Tensor of activations per table specified in the model. There can be at most
        ///    one ReceieveActivations op in the TPU graph.
        /// </remarks>
        public static Tensor[] t_p_u_embedding_receive_activations (int num_tables, string tpu_embedding_config, string name = "TPUEmbeddingReceiveActivations")
        {
            var dict = new Dictionary<string, object>();
            dict["num_tables"] = num_tables;
            dict["tpu_embedding_config"] = tpu_embedding_config;
            var op = _op_def_lib._apply_op_helper("TPUEmbeddingReceiveActivations", name: name, keywords: dict);
            int _idx = 0;
            var outputs = Enumerable.Range(0, op.OutputListLength("outputs")).Select(_ => op.outputs[_idx++]).ToArray();
            return (outputs);
        }

        /// <summary>
        ///    Retrieve an embedding table shard from TPU memory.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TPUEmbeddingRetrieveAdagradParameters'.
        /// </param>
        /// <param name="tpu_embedding_config">
        ///    Optional argument
        ///    Serialized TPUEmbeddingConfiguration proto.
        /// </param>
        /// <param name="table_id">
        ///    Optional argument
        ///    The id of the table specified in the embedding_config_json.
        /// </param>
        /// <param name="num_hosts">
        ///    Optional argument
        ///    The number of CPU hosts in the distributed training job.
        /// </param>
        /// <param name="host_id">
        ///    Optional argument
        ///    Which CPU host in the distributed training job will execute this op.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    parameters :
        ///    accumulators :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    TPU embeddings use dedicated per-optimizer Ops for loading and retrieving
        ///    trainable variables and optimizer state from TPU memory. This op enables
        ///    functionality equivalent to AdagradOptimizer.
        /// </remarks>
        public static (Tensor parameters, Tensor accumulators) t_p_u_embedding_retrieve_adagrad_parameters (string tpu_embedding_config, int table_id, int num_hosts, int host_id, string name = "TPUEmbeddingRetrieveAdagradParameters")
        {
            var dict = new Dictionary<string, object>();
            dict["tpu_embedding_config"] = tpu_embedding_config;
            dict["table_id"] = table_id;
            dict["num_hosts"] = num_hosts;
            dict["host_id"] = host_id;
            var op = _op_def_lib._apply_op_helper("TPUEmbeddingRetrieveAdagradParameters", name: name, keywords: dict);
            int _idx = 0;
            var parameters = op.outputs[_idx++];
            var accumulators = op.outputs[_idx++];
            return (parameters, accumulators);
        }

        /// <summary>
        ///    Retrieve an embedding table shard from TPU memory.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TPUEmbeddingRetrieveGradientDescentParameters'.
        /// </param>
        /// <param name="tpu_embedding_config">
        ///    Optional argument
        ///    Serialized TPUEmbeddingConfiguration proto.
        /// </param>
        /// <param name="table_id">
        ///    Optional argument
        ///    The id of the table specified in tpu_embedding_config.
        /// </param>
        /// <param name="num_hosts">
        ///    Optional argument
        ///    The number of CPU hosts in the distributed training job.
        /// </param>
        /// <param name="host_id">
        ///    Optional argument
        ///    Which CPU host in the distributed training job will execute this op.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    TPU embeddings use dedicated per-optimizer Ops for loading and retrieving
        ///    trainable variables and optimizer state from TPU memory. This op enables
        ///    functionality equivalent to GradientDescentOptimizer.
        /// </remarks>
        public static Tensor t_p_u_embedding_retrieve_gradient_descent_parameters (string tpu_embedding_config, int table_id, int num_hosts, int host_id, string name = "TPUEmbeddingRetrieveGradientDescentParameters")
        {
            var dict = new Dictionary<string, object>();
            dict["tpu_embedding_config"] = tpu_embedding_config;
            dict["table_id"] = table_id;
            dict["num_hosts"] = num_hosts;
            dict["host_id"] = host_id;
            var op = _op_def_lib._apply_op_helper("TPUEmbeddingRetrieveGradientDescentParameters", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    An op that performs gradient updates of embedding tables.
        /// </summary>
        /// <param name="gradients">
        ///    A TensorList of gradients with which to update embedding tables.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TPUEmbeddingSendGradients'.
        /// </param>
        /// <param name="tpu_embedding_config">
        ///    Optional argument
        ///    Serialized TPUEmbeddingConfiguration proto.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    The TensorList argument has the same length and shapes as the return value of
        ///    TPUEmbeddingReceiveActivations, but contains gradients of the model's loss
        ///    with respect to the embedding activations. The embedding tables are updated
        ///    from these gradients via the optimizer specified in the configuration given
        ///    to tpu.initialize_system.
        /// </remarks>
        public static Operation t_p_u_embedding_send_gradients (Tensor[] gradients, string tpu_embedding_config, string name = "TPUEmbeddingSendGradients")
        {
            var dict = new Dictionary<string, object>();
            dict["gradients"] = gradients;
            dict["tpu_embedding_config"] = tpu_embedding_config;
            var op = _op_def_lib._apply_op_helper("TPUEmbeddingSendGradients", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Operator that connects N unreplicated inputs to an N-way replicated TPU computation.
        /// </summary>
        /// <param name="inputs">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TPUReplicatedInput'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor t_p_u_replicated_input (Tensor[] inputs, string name = "TPUReplicatedInput")
        {
            var dict = new Dictionary<string, object>();
            dict["inputs"] = inputs;
            var op = _op_def_lib._apply_op_helper("TPUReplicatedInput", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Operator that connects the output of an N-way replicated TPU computation to N separate outputs.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TPUReplicatedOutput'.
        /// </param>
        /// <param name="num_replicas">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor[] t_p_u_replicated_output (Tensor input, int num_replicas, string name = "TPUReplicatedOutput")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["num_replicas"] = num_replicas;
            var op = _op_def_lib._apply_op_helper("TPUReplicatedOutput", name: name, keywords: dict);
            int _idx = 0;
            var outputs = Enumerable.Range(0, op.OutputListLength("outputs")).Select(_ => op.outputs[_idx++]).ToArray();
            return (outputs);
        }

        /// <summary>
        ///    Creates a dataset that contains <c>count</c> elements from the <c>input_dataset</c>.
        /// </summary>
        /// <param name="input_dataset">
        /// </param>
        /// <param name="count">
        ///    A scalar representing the number of elements from the <c>input_dataset</c>
        ///    that should be taken. A value of <c>-1</c> indicates that all of <c>input_dataset</c>
        ///    is taken.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TakeDataset'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor take_dataset (Tensor input_dataset, Tensor count, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "TakeDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["count"] = count;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("TakeDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Read <c>SparseTensors</c> from a <c>SparseTensorsMap</c> and concatenate them.
        /// </summary>
        /// <param name="sparse_handles">
        ///    1-D, The <c>N</c> serialized <c>SparseTensor</c> objects.
        ///    Shape: <c>[N]</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TakeManySparseFromTensorsMap'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The <c>dtype</c> of the <c>SparseTensor</c> objects stored in the
        ///    <c>SparseTensorsMap</c>.
        /// </param>
        /// <param name="container">
        ///    The container name for the <c>SparseTensorsMap</c> read by this op.
        /// </param>
        /// <param name="shared_name">
        ///    The shared name for the <c>SparseTensorsMap</c> read by this op.
        ///    It should not be blank; rather the <c>shared_name</c> or unique Operation name
        ///    of the Op that created the original <c>SparseTensorsMap</c> should be used.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    sparse_indices : 2-D.  The <c>indices</c> of the minibatch <c>SparseTensor</c>.
        ///    sparse_values : 1-D.  The <c>values</c> of the minibatch <c>SparseTensor</c>.
        ///    sparse_shape : 1-D.  The <c>shape</c> of the minibatch <c>SparseTensor</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    The input <c>sparse_handles</c> must be an <c>int64</c> matrix of shape <c>[N, 1]</c> where
        ///    <c>N</c> is the minibatch size and the rows correspond to the output handles of
        ///    <c>AddSparseToTensorsMap</c> or <c>AddManySparseToTensorsMap</c>.  The ranks of the
        ///    original <c>SparseTensor</c> objects that went into the given input ops must all
        ///    match.  When the final <c>SparseTensor</c> is created, it has rank one
        ///    higher than the ranks of the incoming <c>SparseTensor</c> objects
        ///    (they have been concatenated along a new row dimension on the left).
        ///    
        ///    The output <c>SparseTensor</c> object's shape values for all dimensions but the
        ///    first are the max across the input <c>SparseTensor</c> objects' shape values
        ///    for the corresponding dimensions.  Its first shape value is <c>N</c>, the minibatch
        ///    size.
        ///    
        ///    The input <c>SparseTensor</c> objects' indices are assumed ordered in
        ///    standard lexicographic order.  If this is not the case, after this
        ///    step run <c>SparseReorder</c> to restore index ordering.
        ///    
        ///    For example, if the handles represent an input, which is a <c>[2, 3]</c> matrix
        ///    representing two original <c>SparseTensor</c> objects:
        ///    
        ///   <code>
        ///    index = [ 0]
        ///    [10]
        ///    [20]
        ///    values = [1, 2, 3]
        ///    shape = [50]
        ///   </code>
        ///    
        ///    and
        ///    
        ///   <code>
        ///    index = [ 2]
        ///    [10]
        ///    values = [4, 5]
        ///    shape = [30]
        ///   </code>
        ///    
        ///    then the final <c>SparseTensor</c> will be:
        ///    
        ///   <code>
        ///    index = [0  0]
        ///    [0 10]
        ///    [0 20]
        ///    [1  2]
        ///    [1 10]
        ///    values = [1, 2, 3, 4, 5]
        ///    shape = [2 50]
        ///   </code>
        /// </remarks>
        public static (Tensor sparse_indices, Tensor sparse_values, Tensor sparse_shape) take_many_sparse_from_tensors_map (Tensor sparse_handles, TF_DataType dtype, string container = null, string shared_name = null, string name = "TakeManySparseFromTensorsMap")
        {
            var dict = new Dictionary<string, object>();
            dict["sparse_handles"] = sparse_handles;
            dict["dtype"] = dtype;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("TakeManySparseFromTensorsMap", name: name, keywords: dict);
            int _idx = 0;
            var sparse_indices = op.outputs[_idx++];
            var sparse_values = op.outputs[_idx++];
            var sparse_shape = op.outputs[_idx++];
            return (sparse_indices, sparse_values, sparse_shape);
        }

        /// <summary>
        ///    Computes tan of x element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Tan'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor tan (Tensor x, string name = "Tan")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Tan", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes hyperbolic tangent of <c>x</c> element-wise.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Tanh'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor tanh (Tensor x, string name = "Tanh")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("Tanh", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the gradient for the tanh of <c>x</c> wrt its input.
        /// </summary>
        /// <param name="y">
        /// </param>
        /// <param name="dy">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TanhGrad'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Specifically, <c>grad = dy * (1 - y*y)</c>, where <c>y = tanh(x)</c>, and <c>dy</c>
        ///    is the corresponding input gradient.
        /// </remarks>
        public static Tensor tanh_grad (Tensor y, Tensor dy, string name = "TanhGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["y"] = y;
            dict["dy"] = dy;
            var op = _op_def_lib._apply_op_helper("TanhGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns a tensor that may be mutated, but only persists within a single step.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TemporaryVariable'.
        /// </param>
        /// <param name="shape">
        ///    Optional argument
        ///    The shape of the variable tensor.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The type of elements in the variable tensor.
        /// </param>
        /// <param name="var_name">
        ///    Overrides the name used for the temporary variable resource. Default
        ///    value is the name of the 'TemporaryVariable' op (which is guaranteed unique).
        /// </param>
        /// <returns>
        ///    A reference to the variable tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This is an experimental op for internal use only and it is possible to use this
        ///    op in unsafe ways.  DO NOT USE unless you fully understand the risks.
        ///    
        ///    It is the caller's responsibility to ensure that 'ref' is eventually passed to a
        ///    matching 'DestroyTemporaryVariable' op after all other uses have completed.
        ///    
        ///    Outputs a ref to the tensor state so it may be read or modified.
        ///    
        ///    E.g.
        ///    var = state_ops._temporary_variable([1, 2], types.float_)
        ///    var_name = var.op.name
        ///    var = state_ops.assign(var, [[4.0, 5.0]])
        ///    var = state_ops.assign_add(var, [[6.0, 7.0]])
        ///    final = state_ops._destroy_temporary_variable(var, var_name=var_name)
        /// </remarks>
        public static Tensor temporary_variable (TensorShape shape, TF_DataType dtype, string var_name = null, string name = "TemporaryVariable")
        {
            var dict = new Dictionary<string, object>();
            dict["shape"] = shape;
            dict["dtype"] = dtype;
            if (var_name != null)
                dict["var_name"] = var_name;
            var op = _op_def_lib._apply_op_helper("TemporaryVariable", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Deprecated. Use TensorArrayCloseV3
        /// </summary>
        /// <param name="handle">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArrayCloseV2'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        public static Operation tensor_array_close_v2 (Tensor handle, string name = "TensorArrayCloseV2")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            var op = _op_def_lib._apply_op_helper("TensorArrayCloseV2", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Delete the TensorArray from its resource container.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a TensorArray (output of TensorArray or TensorArrayGrad).
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArrayCloseV3'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    This enables the user to close and release the resource in the middle
        ///    of a step/run.
        /// </remarks>
        public static Operation tensor_array_close_v3 (Tensor handle, string name = "TensorArrayCloseV3")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            var op = _op_def_lib._apply_op_helper("TensorArrayCloseV3", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Deprecated. Use TensorArrayConcatV3
        /// </summary>
        /// <param name="handle">
        /// </param>
        /// <param name="flow_in">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArrayConcatV2'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        /// </param>
        /// <param name="element_shape_except0">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    value :
        ///    lengths :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        public static (Tensor value, Tensor lengths) tensor_array_concat_v2 (Tensor handle, Tensor flow_in, TF_DataType dtype, TensorShape element_shape_except0 = null, string name = "TensorArrayConcatV2")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["flow_in"] = flow_in;
            dict["dtype"] = dtype;
            if (element_shape_except0 != null)
                dict["element_shape_except0"] = element_shape_except0;
            var op = _op_def_lib._apply_op_helper("TensorArrayConcatV2", name: name, keywords: dict);
            int _idx = 0;
            var value = op.outputs[_idx++];
            var lengths = op.outputs[_idx++];
            return (value, lengths);
        }

        /// <summary>
        ///    Concat the elements from the TensorArray into value <c>value</c>.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a TensorArray.
        /// </param>
        /// <param name="flow_in">
        ///    A float scalar that enforces proper chaining of operations.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArrayConcatV3'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The type of the elem that is returned.
        /// </param>
        /// <param name="element_shape_except0">
        ///    The expected shape of an element, if known,
        ///    excluding the first dimension. Used to validate the shapes of
        ///    TensorArray elements. If this shape is not fully specified, concatenating
        ///    zero-size TensorArrays is an error.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    value : All of the elements in the TensorArray, concatenated along the first
        ///    axis.
        ///    lengths : A vector of the row sizes of the original T elements in the
        ///    value output.  In the example above, this would be the values:
        ///    <c>(n1, n2, ..., n(T-1))</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Takes <c>T</c> elements of shapes
        ///    
        ///   <code>
        ///    (n0 x d0 x d1 x ...), (n1 x d0 x d1 x ...), ..., (n(T-1) x d0 x d1 x ...)
        ///   </code>
        ///    
        ///    and concatenates them into a Tensor of shape:
        ///    
        ///   <code>
        ///    (n0 + n1 + ... + n(T-1) x d0 x d1 x ...)
        ///    </code>
        ///    
        ///    All elements must have the same shape (excepting the first dimension).
        /// </remarks>
        public static (Tensor value, Tensor lengths) tensor_array_concat_v3 (Tensor handle, Tensor flow_in, TF_DataType dtype, TensorShape element_shape_except0 = null, string name = "TensorArrayConcatV3")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["flow_in"] = flow_in;
            dict["dtype"] = dtype;
            if (element_shape_except0 != null)
                dict["element_shape_except0"] = element_shape_except0;
            var op = _op_def_lib._apply_op_helper("TensorArrayConcatV3", name: name, keywords: dict);
            int _idx = 0;
            var value = op.outputs[_idx++];
            var lengths = op.outputs[_idx++];
            return (value, lengths);
        }

        /// <summary>
        ///    Deprecated. Use TensorArrayGatherV3
        /// </summary>
        /// <param name="handle">
        /// </param>
        /// <param name="indices">
        /// </param>
        /// <param name="flow_in">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArrayGatherV2'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        /// </param>
        /// <param name="element_shape">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor tensor_array_gather_v2 (Tensor handle, Tensor indices, Tensor flow_in, TF_DataType dtype, TensorShape element_shape = null, string name = "TensorArrayGatherV2")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["indices"] = indices;
            dict["flow_in"] = flow_in;
            dict["dtype"] = dtype;
            if (element_shape != null)
                dict["element_shape"] = element_shape;
            var op = _op_def_lib._apply_op_helper("TensorArrayGatherV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Gather specific elements from the TensorArray into output <c>value</c>.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a TensorArray.
        /// </param>
        /// <param name="indices">
        ///    The locations in the TensorArray from which to read tensor elements.
        /// </param>
        /// <param name="flow_in">
        ///    A float scalar that enforces proper chaining of operations.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArrayGatherV3'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The type of the elem that is returned.
        /// </param>
        /// <param name="element_shape">
        ///    The expected shape of an element, if known. Used to
        ///    validate the shapes of TensorArray elements. If this shape is not
        ///    fully specified, gathering zero-size TensorArrays is an error.
        /// </param>
        /// <returns>
        ///    All of the elements in the TensorArray, concatenated along a new
        ///    axis (the new dimension 0).
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    All elements selected by <c>indices</c> must have the same shape.
        /// </remarks>
        public static Tensor tensor_array_gather_v3 (Tensor handle, Tensor indices, Tensor flow_in, TF_DataType dtype, TensorShape element_shape = null, string name = "TensorArrayGatherV3")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["indices"] = indices;
            dict["flow_in"] = flow_in;
            dict["dtype"] = dtype;
            if (element_shape != null)
                dict["element_shape"] = element_shape;
            var op = _op_def_lib._apply_op_helper("TensorArrayGatherV3", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Deprecated. Use TensorArrayGradV3
        /// </summary>
        /// <param name="handle">
        /// </param>
        /// <param name="flow_in">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArrayGradV2'.
        /// </param>
        /// <param name="source">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor tensor_array_grad_v2 (Tensor handle, Tensor flow_in, string source, string name = "TensorArrayGradV2")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["flow_in"] = flow_in;
            dict["source"] = source;
            var op = _op_def_lib._apply_op_helper("TensorArrayGradV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a TensorArray for storing the gradients of values in the given handle.
        /// </summary>
        /// <param name="handle">
        ///    The handle to the forward TensorArray.
        /// </param>
        /// <param name="flow_in">
        ///    A float scalar that enforces proper chaining of operations.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArrayGradV3'.
        /// </param>
        /// <param name="source">
        ///    Optional argument
        ///    The gradient source string, used to decide which gradient TensorArray
        ///    to return.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    grad_handle :
        ///    flow_out :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    If the given TensorArray gradient already exists, returns a reference to it.
        ///    
        ///    Locks the size of the original TensorArray by disabling its dynamic size flag.
        ///    
        ///    **A note about the input flow_in:**
        ///    
        ///    The handle flow_in forces the execution of the gradient lookup to occur
        ///    only after certain other operations have occurred.  For example, when
        ///    the forward TensorArray is dynamically sized, writes to this TensorArray
        ///    may resize the object.  The gradient TensorArray is statically sized based
        ///    on the size of the forward TensorArray when this operation executes.
        ///    Furthermore, the size of the forward TensorArray is frozen by this call.
        ///    As a result, the flow is used to ensure that the call to generate the gradient
        ///    TensorArray only happens after all writes are executed.
        ///    
        ///    In the case of dynamically sized TensorArrays, gradient computation should
        ///    only be performed on read operations that have themselves been chained via
        ///    flow to occur only after all writes have executed. That way the final size
        ///    of the forward TensorArray is known when this operation is called.
        ///    
        ///    **A note about the source attribute:**
        ///    
        ///    TensorArray gradient calls use an accumulator TensorArray object.  If
        ///    multiple gradients are calculated and run in the same session, the multiple
        ///    gradient nodes may accidentally flow through the same accumulator TensorArray.
        ///    This double counts and generally breaks the TensorArray gradient flow.
        ///    
        ///    The solution is to identify which gradient call this particular
        ///    TensorArray gradient is being called in.  This is performed by identifying
        ///    a unique string (e.g. "gradients", "gradients_1", ...) from the input
        ///    gradient Tensor's name.  This string is used as a suffix when creating
        ///    the TensorArray gradient object here (the attribute <c>source</c>).
        ///    
        ///    The attribute <c>source</c> is added as a suffix to the forward TensorArray's
        ///    name when performing the creation / lookup, so that each separate gradient
        ///    calculation gets its own TensorArray accumulator.
        /// </remarks>
        public static (Tensor grad_handle, Tensor flow_out) tensor_array_grad_v3 (Tensor handle, Tensor flow_in, string source, string name = "TensorArrayGradV3")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["flow_in"] = flow_in;
            dict["source"] = source;
            var op = _op_def_lib._apply_op_helper("TensorArrayGradV3", name: name, keywords: dict);
            int _idx = 0;
            var grad_handle = op.outputs[_idx++];
            var flow_out = op.outputs[_idx++];
            return (grad_handle, flow_out);
        }

        /// <summary>
        ///    Creates a TensorArray for storing multiple gradients of values in the given handle.
        /// </summary>
        /// <param name="handle">
        ///    The handle to the forward TensorArray.
        /// </param>
        /// <param name="flow_in">
        ///    A float scalar that enforces proper chaining of operations.
        /// </param>
        /// <param name="shape_to_prepend">
        ///    An int32 vector representing a shape. Elements in the gradient accumulator will
        ///    have shape which is this shape_to_prepend value concatenated with shape of the
        ///    elements in the TensorArray corresponding to the input handle.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArrayGradWithShape'.
        /// </param>
        /// <param name="source">
        ///    Optional argument
        ///    The gradient source string, used to decide which gradient TensorArray
        ///    to return.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    grad_handle :
        ///    flow_out :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Similar to TensorArrayGradV3. However it creates an accumulator with an
        ///    expanded shape compared to the input TensorArray whose gradient is being
        ///    computed. This enables multiple gradients for the same TensorArray to be
        ///    calculated using the same accumulator.
        /// </remarks>
        public static (Tensor grad_handle, Tensor flow_out) tensor_array_grad_with_shape (Tensor handle, Tensor flow_in, Tensor shape_to_prepend, string source, string name = "TensorArrayGradWithShape")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["flow_in"] = flow_in;
            dict["shape_to_prepend"] = shape_to_prepend;
            dict["source"] = source;
            var op = _op_def_lib._apply_op_helper("TensorArrayGradWithShape", name: name, keywords: dict);
            int _idx = 0;
            var grad_handle = op.outputs[_idx++];
            var flow_out = op.outputs[_idx++];
            return (grad_handle, flow_out);
        }

        /// <summary>
        ///    Deprecated. Use TensorArrayReadV3
        /// </summary>
        /// <param name="handle">
        /// </param>
        /// <param name="index">
        /// </param>
        /// <param name="flow_in">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArrayReadV2'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor tensor_array_read_v2 (Tensor handle, Tensor index, Tensor flow_in, TF_DataType dtype, string name = "TensorArrayReadV2")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["index"] = index;
            dict["flow_in"] = flow_in;
            dict["dtype"] = dtype;
            var op = _op_def_lib._apply_op_helper("TensorArrayReadV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Read an element from the TensorArray into output <c>value</c>.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a TensorArray.
        /// </param>
        /// <param name="index">
        /// </param>
        /// <param name="flow_in">
        ///    A float scalar that enforces proper chaining of operations.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArrayReadV3'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The type of the elem that is returned.
        /// </param>
        /// <returns>
        ///    The tensor that is read from the TensorArray.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor tensor_array_read_v3 (Tensor handle, Tensor index, Tensor flow_in, TF_DataType dtype, string name = "TensorArrayReadV3")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["index"] = index;
            dict["flow_in"] = flow_in;
            dict["dtype"] = dtype;
            var op = _op_def_lib._apply_op_helper("TensorArrayReadV3", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Deprecated. Use TensorArrayScatterV3
        /// </summary>
        /// <param name="handle">
        /// </param>
        /// <param name="indices">
        /// </param>
        /// <param name="value">
        /// </param>
        /// <param name="flow_in">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArrayScatterV2'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor tensor_array_scatter_v2 (Tensor handle, Tensor indices, Tensor value, Tensor flow_in, string name = "TensorArrayScatterV2")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["indices"] = indices;
            dict["value"] = value;
            dict["flow_in"] = flow_in;
            var op = _op_def_lib._apply_op_helper("TensorArrayScatterV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Scatter the data from the input value into specific TensorArray elements.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a TensorArray.
        /// </param>
        /// <param name="indices">
        ///    The locations at which to write the tensor elements.
        /// </param>
        /// <param name="value">
        ///    The concatenated tensor to write to the TensorArray.
        /// </param>
        /// <param name="flow_in">
        ///    A float scalar that enforces proper chaining of operations.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArrayScatterV3'.
        /// </param>
        /// <returns>
        ///    A float scalar that enforces proper chaining of operations.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    <c>indices</c> must be a vector, its length must match the first dim of <c>value</c>.
        /// </remarks>
        public static Tensor tensor_array_scatter_v3 (Tensor handle, Tensor indices, Tensor value, Tensor flow_in, string name = "TensorArrayScatterV3")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["indices"] = indices;
            dict["value"] = value;
            dict["flow_in"] = flow_in;
            var op = _op_def_lib._apply_op_helper("TensorArrayScatterV3", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Deprecated. Use TensorArraySizeV3
        /// </summary>
        /// <param name="handle">
        /// </param>
        /// <param name="flow_in">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArraySizeV2'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor tensor_array_size_v2 (Tensor handle, Tensor flow_in, string name = "TensorArraySizeV2")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["flow_in"] = flow_in;
            var op = _op_def_lib._apply_op_helper("TensorArraySizeV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Get the current size of the TensorArray.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a TensorArray (output of TensorArray or TensorArrayGrad).
        /// </param>
        /// <param name="flow_in">
        ///    A float scalar that enforces proper chaining of operations.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArraySizeV3'.
        /// </param>
        /// <returns>
        ///    The current size of the TensorArray.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor tensor_array_size_v3 (Tensor handle, Tensor flow_in, string name = "TensorArraySizeV3")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["flow_in"] = flow_in;
            var op = _op_def_lib._apply_op_helper("TensorArraySizeV3", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Deprecated. Use TensorArraySplitV3
        /// </summary>
        /// <param name="handle">
        /// </param>
        /// <param name="value">
        /// </param>
        /// <param name="lengths">
        /// </param>
        /// <param name="flow_in">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArraySplitV2'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor tensor_array_split_v2 (Tensor handle, Tensor value, Tensor lengths, Tensor flow_in, string name = "TensorArraySplitV2")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["value"] = value;
            dict["lengths"] = lengths;
            dict["flow_in"] = flow_in;
            var op = _op_def_lib._apply_op_helper("TensorArraySplitV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Split the data from the input value into TensorArray elements.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a TensorArray.
        /// </param>
        /// <param name="value">
        ///    The concatenated tensor to write to the TensorArray.
        /// </param>
        /// <param name="lengths">
        ///    The vector of lengths, how to split the rows of value into the
        ///    TensorArray.
        /// </param>
        /// <param name="flow_in">
        ///    A float scalar that enforces proper chaining of operations.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArraySplitV3'.
        /// </param>
        /// <returns>
        ///    A float scalar that enforces proper chaining of operations.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Assuming that <c>lengths</c> takes on values
        ///    
        ///   <code>
        ///    (n0, n1, ..., n(T-1))
        ///    </code>
        ///    
        ///    and that <c>value</c> has shape
        ///    
        ///   <code>
        ///    (n0 + n1 + ... + n(T-1) x d0 x d1 x ...)<c></c><c>,
        ///    
        ///    this splits values into a TensorArray with T tensors.
        ///    
        ///    TensorArray index t will be the subtensor of values with starting position
        ///    
        ///   </code>
        ///    (n0 + n1 + ... + n(t-1), 0, 0, ...)
        ///    <code>
        ///    
        ///    and having size
        ///    
        ///   </code>
        ///    nt x d0 x d1 x ...
        ///    <code>
        /// </remarks>
        public static Tensor tensor_array_split_v3 (Tensor handle, Tensor value, Tensor lengths, Tensor flow_in, string name = "TensorArraySplitV3")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["value"] = value;
            dict["lengths"] = lengths;
            dict["flow_in"] = flow_in;
            var op = _op_def_lib._apply_op_helper("TensorArraySplitV3", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Deprecated. Use TensorArrayV3
        /// </summary>
        /// <param name="size">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArrayV2'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        /// </param>
        /// <param name="element_shape">
        /// </param>
        /// <param name="dynamic_size">
        /// </param>
        /// <param name="clear_after_read">
        /// </param>
        /// <param name="tensor_array_name">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor tensor_array_v2 (Tensor size, TF_DataType dtype, TensorShape element_shape = null, bool? dynamic_size = null, bool? clear_after_read = null, string tensor_array_name = null, string name = "TensorArrayV2")
        {
            var dict = new Dictionary<string, object>();
            dict["size"] = size;
            dict["dtype"] = dtype;
            if (element_shape != null)
                dict["element_shape"] = element_shape;
            if (dynamic_size.HasValue)
                dict["dynamic_size"] = dynamic_size.Value;
            if (clear_after_read.HasValue)
                dict["clear_after_read"] = clear_after_read.Value;
            if (tensor_array_name != null)
                dict["tensor_array_name"] = tensor_array_name;
            var op = _op_def_lib._apply_op_helper("TensorArrayV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    An array of Tensors of given size.
        /// </summary>
        /// <param name="size">
        ///    The size of the array.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArrayV3'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The type of the elements on the tensor_array.
        /// </param>
        /// <param name="element_shape">
        ///    The expected shape of an element, if known. Used to
        ///    validate the shapes of TensorArray elements. If this shape is not
        ///    fully specified, gathering zero-size TensorArrays is an error.
        /// </param>
        /// <param name="dynamic_size">
        ///    A boolean that determines whether writes to the TensorArray
        ///    are allowed to grow the size.  By default, this is not allowed.
        /// </param>
        /// <param name="clear_after_read">
        ///    If true (default), Tensors in the TensorArray are cleared
        ///    after being read.  This disables multiple read semantics but allows early
        ///    release of memory.
        /// </param>
        /// <param name="identical_element_shapes">
        ///    If true (default is false), then all
        ///    elements in the TensorArray will be expected to have have identical shapes.
        ///    This allows certain behaviors, like dynamically checking for
        ///    consistent shapes on write, and being able to fill in properly
        ///    shaped zero tensors on stack -- even if the element_shape attribute
        ///    is not fully defined.
        /// </param>
        /// <param name="tensor_array_name">
        ///    Overrides the name used for the temporary tensor_array
        ///    resource. Default value is the name of the 'TensorArray' op (which
        ///    is guaranteed unique).
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    handle : The handle to the TensorArray.
        ///    flow : A scalar used to control gradient flow.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Write data via Write and read via Read or Pack.
        /// </remarks>
        public static (Tensor handle, Tensor flow) tensor_array_v3 (Tensor size, TF_DataType dtype, TensorShape element_shape = null, bool? dynamic_size = null, bool? clear_after_read = null, bool? identical_element_shapes = null, string tensor_array_name = null, string name = "TensorArrayV3")
        {
            var dict = new Dictionary<string, object>();
            dict["size"] = size;
            dict["dtype"] = dtype;
            if (element_shape != null)
                dict["element_shape"] = element_shape;
            if (dynamic_size.HasValue)
                dict["dynamic_size"] = dynamic_size.Value;
            if (clear_after_read.HasValue)
                dict["clear_after_read"] = clear_after_read.Value;
            if (identical_element_shapes.HasValue)
                dict["identical_element_shapes"] = identical_element_shapes.Value;
            if (tensor_array_name != null)
                dict["tensor_array_name"] = tensor_array_name;
            var op = _op_def_lib._apply_op_helper("TensorArrayV3", name: name, keywords: dict);
            int _idx = 0;
            var handle = op.outputs[_idx++];
            var flow = op.outputs[_idx++];
            return (handle, flow);
        }

        /// <summary>
        ///    Deprecated. Use TensorArrayGradV3
        /// </summary>
        /// <param name="handle">
        /// </param>
        /// <param name="index">
        /// </param>
        /// <param name="value">
        /// </param>
        /// <param name="flow_in">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArrayWriteV2'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor tensor_array_write_v2 (Tensor handle, Tensor index, Tensor value, Tensor flow_in, string name = "TensorArrayWriteV2")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["index"] = index;
            dict["value"] = value;
            dict["flow_in"] = flow_in;
            var op = _op_def_lib._apply_op_helper("TensorArrayWriteV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Push an element onto the tensor_array.
        /// </summary>
        /// <param name="handle">
        ///    The handle to a TensorArray.
        /// </param>
        /// <param name="index">
        ///    The position to write to inside the TensorArray.
        /// </param>
        /// <param name="value">
        ///    The tensor to write to the TensorArray.
        /// </param>
        /// <param name="flow_in">
        ///    A float scalar that enforces proper chaining of operations.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorArrayWriteV3'.
        /// </param>
        /// <returns>
        ///    A float scalar that enforces proper chaining of operations.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor tensor_array_write_v3 (Tensor handle, Tensor index, Tensor value, Tensor flow_in, string name = "TensorArrayWriteV3")
        {
            var dict = new Dictionary<string, object>();
            dict["handle"] = handle;
            dict["index"] = index;
            dict["value"] = value;
            dict["flow_in"] = flow_in;
            var op = _op_def_lib._apply_op_helper("TensorArrayWriteV3", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a dataset that emits <c>components</c> as a tuple of tensors once.
        /// </summary>
        /// <param name="components">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorDataset'.
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor tensor_dataset (Tensor[] components, TensorShape[] output_shapes, string name = "TensorDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["components"] = components;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("TensorDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    The shape of the elements of the given list, as a tensor.
        /// </summary>
        /// <param name="input_handle">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorListElementShape'.
        /// </param>
        /// <param name="shape_type">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    input_handle: the list
        ///    element_shape: the shape of elements of the list
        /// </remarks>
        public static Tensor tensor_list_element_shape (Tensor input_handle, TF_DataType shape_type, string name = "TensorListElementShape")
        {
            var dict = new Dictionary<string, object>();
            dict["input_handle"] = input_handle;
            dict["shape_type"] = shape_type;
            var op = _op_def_lib._apply_op_helper("TensorListElementShape", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a TensorList which, when stacked, has the value of <c>tensor</c>.
        /// </summary>
        /// <param name="tensor">
        /// </param>
        /// <param name="element_shape">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorListFromTensor'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Each tensor in the result list corresponds to one row of the input tensor.
        ///    
        ///    tensor: The input tensor.
        ///    output_handle: The list.
        /// </remarks>
        public static Tensor tensor_list_from_tensor (Tensor tensor, Tensor element_shape, string name = "TensorListFromTensor")
        {
            var dict = new Dictionary<string, object>();
            dict["tensor"] = tensor;
            dict["element_shape"] = element_shape;
            var op = _op_def_lib._apply_op_helper("TensorListFromTensor", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a Tensor by indexing into the TensorList.
        /// </summary>
        /// <param name="input_handle">
        /// </param>
        /// <param name="indices">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorListGather'.
        /// </param>
        /// <param name="element_dtype">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Each row in the produced Tensor corresponds to the element in the TensorList
        ///    specified by the given index (see <c>tf.gather</c>).
        ///    
        ///    input_handle: The input tensor list.
        ///    indices: The indices used to index into the list.
        ///    values: The tensor.
        /// </remarks>
        public static Tensor tensor_list_gather (Tensor input_handle, Tensor indices, TF_DataType element_dtype, string name = "TensorListGather")
        {
            var dict = new Dictionary<string, object>();
            dict["input_handle"] = input_handle;
            dict["indices"] = indices;
            dict["element_dtype"] = element_dtype;
            var op = _op_def_lib._apply_op_helper("TensorListGather", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the item in the list with the given index.
        /// </summary>
        /// <param name="input_handle">
        /// </param>
        /// <param name="index">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorListGetItem'.
        /// </param>
        /// <param name="element_dtype">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    input_handle: the list
        ///    index: the position in the list from which an element will be retrieved
        ///    item: the element at that position
        ///    
        ///    
        /// </remarks>
        public static Tensor tensor_list_get_item (Tensor input_handle, Tensor index, TF_DataType element_dtype, string name = "TensorListGetItem")
        {
            var dict = new Dictionary<string, object>();
            dict["input_handle"] = input_handle;
            dict["index"] = index;
            dict["element_dtype"] = element_dtype;
            var op = _op_def_lib._apply_op_helper("TensorListGetItem", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the number of tensors in the input tensor list.
        /// </summary>
        /// <param name="input_handle">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorListLength'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    input_handle: the input list
        ///    length: the number of tensors in the list
        /// </remarks>
        public static Tensor tensor_list_length (Tensor input_handle, string name = "TensorListLength")
        {
            var dict = new Dictionary<string, object>();
            dict["input_handle"] = input_handle;
            var op = _op_def_lib._apply_op_helper("TensorListLength", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the last element of the input list as well as a list with all but that element.
        /// </summary>
        /// <param name="input_handle">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorListPopBack'.
        /// </param>
        /// <param name="element_dtype">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    output_handle :
        ///    tensor :
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    Fails if the list is empty.
        ///    
        ///    input_handle: the input list
        ///    tensor: the withdrawn last element of the list
        ///    element_dtype: the type of elements in the list
        ///    element_shape: the shape of the output tensor
        /// </remarks>
        public static (Tensor output_handle, Tensor tensor) tensor_list_pop_back (Tensor input_handle, TF_DataType element_dtype, string name = "TensorListPopBack")
        {
            var dict = new Dictionary<string, object>();
            dict["input_handle"] = input_handle;
            dict["element_dtype"] = element_dtype;
            var op = _op_def_lib._apply_op_helper("TensorListPopBack", name: name, keywords: dict);
            int _idx = 0;
            var output_handle = op.outputs[_idx++];
            var tensor = op.outputs[_idx++];
            return (output_handle, tensor);
        }

        /// <summary>
        ///    Returns a list list which has the passed-in <c>Tensor</c> as last element and the other elements of the given list in <c>input_handle</c>.
        /// </summary>
        /// <param name="input_handle">
        /// </param>
        /// <param name="tensor">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorListPushBack'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    tensor: The tensor to put on the list.
        ///    input_handle: The old list.
        ///    output_handle: A list with the elements of the old list followed by tensor.
        ///    element_dtype: the type of elements in the list.
        ///    element_shape: a shape compatible with that of elements in the list.
        /// </remarks>
        public static Tensor tensor_list_push_back (Tensor input_handle, Tensor tensor, string name = "TensorListPushBack")
        {
            var dict = new Dictionary<string, object>();
            dict["input_handle"] = input_handle;
            dict["tensor"] = tensor;
            var op = _op_def_lib._apply_op_helper("TensorListPushBack", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    List of the given size with empty elements.
        /// </summary>
        /// <param name="element_shape">
        /// </param>
        /// <param name="num_elements">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorListReserve'.
        /// </param>
        /// <param name="element_dtype">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    element_shape: the shape of the future elements of the list
        ///    num_elements: the number of elements to reserve
        ///    handle: the output list
        ///    element_dtype: the desired type of elements in the list.
        /// </remarks>
        public static Tensor tensor_list_reserve (Tensor element_shape, Tensor num_elements, TF_DataType element_dtype, string name = "TensorListReserve")
        {
            var dict = new Dictionary<string, object>();
            dict["element_shape"] = element_shape;
            dict["num_elements"] = num_elements;
            dict["element_dtype"] = element_dtype;
            var op = _op_def_lib._apply_op_helper("TensorListReserve", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a TensorList by indexing into a Tensor.
        /// </summary>
        /// <param name="tensor">
        /// </param>
        /// <param name="indices">
        /// </param>
        /// <param name="element_shape">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorListScatter'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Each member of the TensorList corresponds to one row of the input tensor,
        ///    specified by the given index (see <c>tf.gather</c>).
        ///    
        ///    tensor: The input tensor.
        ///    indices: The indices used to index into the list.
        ///    element_shape: The shape of the elements in the list (can be less specified than
        ///    the shape of the tensor).
        ///    output_handle: The TensorList.
        /// </remarks>
        public static Tensor tensor_list_scatter (Tensor tensor, Tensor indices, Tensor element_shape, string name = "TensorListScatter")
        {
            var dict = new Dictionary<string, object>();
            dict["tensor"] = tensor;
            dict["indices"] = indices;
            dict["element_shape"] = element_shape;
            var op = _op_def_lib._apply_op_helper("TensorListScatter", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Sets the index-th position of the list to contain the given tensor.
        /// </summary>
        /// <param name="input_handle">
        /// </param>
        /// <param name="index">
        /// </param>
        /// <param name="item">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorListSetItem'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    input_handle: the list
        ///    index: the position in the list to which the tensor will be assigned
        ///    item: the element to be assigned to that position
        ///    output_handle: the new list, with the element in the proper position
        ///    
        /// </remarks>
        public static Tensor tensor_list_set_item (Tensor input_handle, Tensor index, Tensor item, string name = "TensorListSetItem")
        {
            var dict = new Dictionary<string, object>();
            dict["input_handle"] = input_handle;
            dict["index"] = index;
            dict["item"] = item;
            var op = _op_def_lib._apply_op_helper("TensorListSetItem", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Stacks all tensors in the list.
        /// </summary>
        /// <param name="input_handle">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorListStack'.
        /// </param>
        /// <param name="element_dtype">
        ///    Optional argument
        /// </param>
        /// <param name="num_elements">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Requires that all tensors have the same shape.
        ///    
        ///    input_handle: the input list
        ///    tensor: the gathered result
        ///    num_elements: optional. If not -1, the number of elements in the list.
        ///    
        /// </remarks>
        public static Tensor tensor_list_stack (Tensor input_handle, TF_DataType element_dtype, int? num_elements = null, string name = "TensorListStack")
        {
            var dict = new Dictionary<string, object>();
            dict["input_handle"] = input_handle;
            dict["element_dtype"] = element_dtype;
            if (num_elements.HasValue)
                dict["num_elements"] = num_elements.Value;
            var op = _op_def_lib._apply_op_helper("TensorListStack", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a dataset that emits each dim-0 slice of <c>components</c> once.
        /// </summary>
        /// <param name="components">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorSliceDataset'.
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor tensor_slice_dataset (Tensor[] components, TensorShape[] output_shapes, string name = "TensorSliceDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["components"] = components;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("TensorSliceDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Outputs a <c>Summary</c> protocol buffer with a tensor.
        /// </summary>
        /// <param name="tensor">
        ///    A tensor to serialize.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorSummary'.
        /// </param>
        /// <param name="description">
        ///    A json-encoded SummaryDescription proto.
        /// </param>
        /// <param name="labels">
        ///    An unused list of strings.
        /// </param>
        /// <param name="display_name">
        ///    An unused string.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This op is being phased out in favor of TensorSummaryV2, which lets callers pass
        ///    a tag as well as a serialized SummaryMetadata proto string that contains
        ///    plugin-specific data. We will keep this op to maintain backwards compatibility.
        /// </remarks>
        public static Tensor tensor_summary (Tensor tensor, string description = null, string[] labels = null, string display_name = null, string name = "TensorSummary")
        {
            var dict = new Dictionary<string, object>();
            dict["tensor"] = tensor;
            if (description != null)
                dict["description"] = description;
            if (labels != null)
                dict["labels"] = labels;
            if (display_name != null)
                dict["display_name"] = display_name;
            var op = _op_def_lib._apply_op_helper("TensorSummary", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Outputs a <c>Summary</c> protocol buffer with a tensor and per-plugin data.
        /// </summary>
        /// <param name="tag">
        ///    A string attached to this summary. Used for organization in TensorBoard.
        /// </param>
        /// <param name="tensor">
        ///    A tensor to serialize.
        /// </param>
        /// <param name="serialized_summary_metadata">
        ///    A serialized SummaryMetadata proto. Contains plugin
        ///    data.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TensorSummaryV2'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor tensor_summary_v2 (Tensor tag, Tensor tensor, Tensor serialized_summary_metadata, string name = "TensorSummaryV2")
        {
            var dict = new Dictionary<string, object>();
            dict["tag"] = tag;
            dict["tensor"] = tensor;
            dict["serialized_summary_metadata"] = serialized_summary_metadata;
            var op = _op_def_lib._apply_op_helper("TensorSummaryV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a dataset that emits the lines of one or more text files.
        /// </summary>
        /// <param name="filenames">
        ///    A scalar or a vector containing the name(s) of the file(s) to be
        ///    read.
        /// </param>
        /// <param name="compression_type">
        ///    A scalar containing either (i) the empty string (no
        ///    compression), (ii) "ZLIB", or (iii) "GZIP".
        /// </param>
        /// <param name="buffer_size">
        ///    A scalar containing the number of bytes to buffer.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TextLineDataset'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor text_line_dataset (Tensor filenames, Tensor compression_type, Tensor buffer_size, string name = "TextLineDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["filenames"] = filenames;
            dict["compression_type"] = compression_type;
            dict["buffer_size"] = buffer_size;
            var op = _op_def_lib._apply_op_helper("TextLineDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A Reader that outputs the lines of a file delimited by '\n'.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TextLineReader'.
        /// </param>
        /// <param name="skip_header_lines">
        ///    Number of lines to skip from the beginning of every file.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this reader is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this reader is named in the given bucket
        ///    with this shared_name. Otherwise, the node name is used instead.
        /// </param>
        /// <returns>
        ///    The handle to reference the Reader.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor text_line_reader (int? skip_header_lines = null, string container = null, string shared_name = null, string name = "TextLineReader")
        {
            var dict = new Dictionary<string, object>();
            if (skip_header_lines.HasValue)
                dict["skip_header_lines"] = skip_header_lines.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("TextLineReader", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A Reader that outputs the lines of a file delimited by '\n'.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TextLineReaderV2'.
        /// </param>
        /// <param name="skip_header_lines">
        ///    Number of lines to skip from the beginning of every file.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this reader is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this reader is named in the given bucket
        ///    with this shared_name. Otherwise, the node name is used instead.
        /// </param>
        /// <returns>
        ///    The handle to reference the Reader.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor text_line_reader_v2 (int? skip_header_lines = null, string container = null, string shared_name = null, string name = "TextLineReaderV2")
        {
            var dict = new Dictionary<string, object>();
            if (skip_header_lines.HasValue)
                dict["skip_header_lines"] = skip_header_lines.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("TextLineReaderV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Generates labels for candidate sampling with a learned unigram distribution.
        /// </summary>
        /// <param name="true_classes">
        ///    A batch_size * num_true matrix, in which each row contains the
        ///    IDs of the num_true target_classes in the corresponding original label.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ThreadUnsafeUnigramCandidateSampler'.
        /// </param>
        /// <param name="num_true">
        ///    Optional argument
        ///    Number of true labels per context.
        /// </param>
        /// <param name="num_sampled">
        ///    Optional argument
        ///    Number of candidates to randomly sample.
        /// </param>
        /// <param name="unique">
        ///    Optional argument
        ///    If unique is true, we sample with rejection, so that all sampled
        ///    candidates in a batch are unique. This requires some approximation to
        ///    estimate the post-rejection sampling probabilities.
        /// </param>
        /// <param name="range_max">
        ///    Optional argument
        ///    The sampler will sample integers from the interval [0, range_max).
        /// </param>
        /// <param name="seed">
        ///    If either seed or seed2 are set to be non-zero, the random number
        ///    generator is seeded by the given seed.  Otherwise, it is seeded by a
        ///    random seed.
        /// </param>
        /// <param name="seed2">
        ///    An second seed to avoid seed collision.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    sampled_candidates : A vector of length num_sampled, in which each element is
        ///    the ID of a sampled candidate.
        ///    true_expected_count : A batch_size * num_true matrix, representing
        ///    the number of times each candidate is expected to occur in a batch
        ///    of sampled candidates. If unique=true, then this is a probability.
        ///    sampled_expected_count : A vector of length num_sampled, for each sampled
        ///    candidate representing the number of times the candidate is expected
        ///    to occur in a batch of sampled candidates.  If unique=true, then this is a
        ///    probability.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    See explanations of candidate sampling and the data formats at
        ///    go/candidate-sampling.
        ///    
        ///    For each batch, this op picks a single set of sampled candidate labels.
        ///    
        ///    The advantages of sampling candidates per-batch are simplicity and the
        ///    possibility of efficient dense matrix multiplication. The disadvantage is that
        ///    the sampled candidates must be chosen independently of the context and of the
        ///    true labels.
        /// </remarks>
        public static (Tensor sampled_candidates, Tensor true_expected_count, Tensor sampled_expected_count) thread_unsafe_unigram_candidate_sampler (Tensor true_classes, int num_true, int num_sampled, bool unique, int range_max, int? seed = null, int? seed2 = null, string name = "ThreadUnsafeUnigramCandidateSampler")
        {
            var dict = new Dictionary<string, object>();
            dict["true_classes"] = true_classes;
            dict["num_true"] = num_true;
            dict["num_sampled"] = num_sampled;
            dict["unique"] = unique;
            dict["range_max"] = range_max;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("ThreadUnsafeUnigramCandidateSampler", name: name, keywords: dict);
            int _idx = 0;
            var sampled_candidates = op.outputs[_idx++];
            var true_expected_count = op.outputs[_idx++];
            var sampled_expected_count = op.outputs[_idx++];
            return (sampled_candidates, true_expected_count, sampled_expected_count);
        }

        /// <summary>
        ///    Constructs a tensor by tiling a given tensor.
        /// </summary>
        /// <param name="input">
        ///    1-D or higher.
        /// </param>
        /// <param name="multiples">
        ///    1-D. Length must be the same as the number of dimensions in <c>input</c>
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Tile'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation creates a new tensor by replicating <c>input</c> <c>multiples</c> times.
        ///    The output tensor's i'th dimension has <c>input.dims(i) * multiples[i]</c> elements,
        ///    and the values of <c>input</c> are replicated <c>multiples[i]</c> times along the 'i'th
        ///    dimension. For example, tiling <c>[a b c d]</c> by <c>[2]</c> produces
        ///    <c>[a b c d a b c d]</c>.
        /// </remarks>
        public static Tensor tile (Tensor input, Tensor multiples, string name = "Tile")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["multiples"] = multiples;
            var op = _op_def_lib._apply_op_helper("Tile", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the gradient of <c>Tile</c>.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="multiples">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TileGrad'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Since <c>Tile</c> takes an input and repeats the input <c>multiples</c> times
        ///    along each dimension, <c>TileGrad</c> takes in <c>multiples</c> and aggregates
        ///    each repeated tile of <c>input</c> into <c>output</c>.
        /// </remarks>
        public static Tensor tile_grad (Tensor input, Tensor multiples, string name = "TileGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["multiples"] = multiples;
            var op = _op_def_lib._apply_op_helper("TileGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Provides the time since epoch in seconds.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Timestamp'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Returns the timestamp as a <c>float64</c> for seconds since the Unix epoch.
        ///    
        ///    Note: the timestamp is computed when the op is executed, not when it is added
        ///    to the graph.
        /// </remarks>
        public static Tensor timestamp (string name = "Timestamp")
        {
            var dict = new Dictionary<string, object>();
            var op = _op_def_lib._apply_op_helper("Timestamp", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Finds values and indices of the <c>k</c> largest elements for the last dimension.
        /// </summary>
        /// <param name="input">
        ///    1-D or higher with last dimension at least <c>k</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TopK'.
        /// </param>
        /// <param name="k">
        ///    Optional argument
        ///    Number of top elements to look for along the last dimension (along each
        ///    row for matrices).
        /// </param>
        /// <param name="sorted">
        ///    If true the resulting <c>k</c> elements will be sorted by the values in
        ///    descending order.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    values : The <c>k</c> largest elements along each last dimensional slice.
        ///    indices : The indices of <c>values</c> within the last dimension of <c>input</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    If the input is a vector (rank-1), finds the <c>k</c> largest entries in the vector
        ///    and outputs their values and indices as vectors.  Thus <c>values[j]</c> is the
        ///    <c>j</c>-th largest entry in <c>input</c>, and its index is <c>indices[j]</c>.
        ///    
        ///    For matrices (resp. higher rank input), computes the top <c>k</c> entries in each
        ///    row (resp. vector along the last dimension).  Thus,
        ///    
        ///    values.shape = indices.shape = input.shape[:-1] + [k]
        ///    
        ///    If two elements are equal, the lower-index element appears first.
        ///    
        ///    If <c>k</c> varies dynamically, use <c>TopKV2</c> below.
        /// </remarks>
        public static (Tensor values, Tensor indices) top_k (Tensor input, int k, bool? sorted = null, string name = "TopK")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["k"] = k;
            if (sorted.HasValue)
                dict["sorted"] = sorted.Value;
            var op = _op_def_lib._apply_op_helper("TopK", name: name, keywords: dict);
            int _idx = 0;
            var values = op.outputs[_idx++];
            var indices = op.outputs[_idx++];
            return (values, indices);
        }

        /// <summary>
        ///    Finds values and indices of the <c>k</c> largest elements for the last dimension.
        /// </summary>
        /// <param name="input">
        ///    1-D or higher with last dimension at least <c>k</c>.
        /// </param>
        /// <param name="k">
        ///    0-D.  Number of top elements to look for along the last dimension (along each
        ///    row for matrices).
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TopKV2'.
        /// </param>
        /// <param name="sorted">
        ///    If true the resulting <c>k</c> elements will be sorted by the values in
        ///    descending order.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    values : The <c>k</c> largest elements along each last dimensional slice.
        ///    indices : The indices of <c>values</c> within the last dimension of <c>input</c>.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    If the input is a vector (rank-1), finds the <c>k</c> largest entries in the vector
        ///    and outputs their values and indices as vectors.  Thus <c>values[j]</c> is the
        ///    <c>j</c>-th largest entry in <c>input</c>, and its index is <c>indices[j]</c>.
        ///    
        ///    For matrices (resp. higher rank input), computes the top <c>k</c> entries in each
        ///    row (resp. vector along the last dimension).  Thus,
        ///    
        ///    values.shape = indices.shape = input.shape[:-1] + [k]
        ///    
        ///    If two elements are equal, the lower-index element appears first.
        /// </remarks>
        public static (Tensor values, Tensor indices) top_k_v2 (Tensor input, Tensor k, bool? sorted = null, string name = "TopKV2")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            dict["k"] = k;
            if (sorted.HasValue)
                dict["sorted"] = sorted.Value;
            var op = _op_def_lib._apply_op_helper("TopKV2", name: name, keywords: dict);
            int _idx = 0;
            var values = op.outputs[_idx++];
            var indices = op.outputs[_idx++];
            return (values, indices);
        }

        /// <summary>
        ///    Shuffle dimensions of x according to a permutation.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="perm">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Transpose'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The output <c>y</c> has the same rank as <c>x</c>. The shapes of <c>x</c> and <c>y</c> satisfy:
        ///    <c>y.shape[i] == x.shape[perm[i]] for i in [0, 1, ..., rank(x) - 1]</c>
        /// </remarks>
        public static Tensor transpose (Tensor x, Tensor perm, string name = "Transpose")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["perm"] = perm;
            var op = _op_def_lib._apply_op_helper("Transpose", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns x / y element-wise for integer types.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TruncateDiv'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Truncation designates that negative numbers will round fractional quantities
        ///    toward zero. I.e. -7 / 5 = -1. This matches C semantics but it is different
        ///    than Python semantics. See <c>FloorDiv</c> for a division function that matches
        ///    Python Semantics.
        ///    
        ///    *NOTE*: <c>TruncateDiv</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor truncate_div (Tensor x, Tensor y, string name = "TruncateDiv")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("TruncateDiv", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns element-wise remainder of division. This emulates C semantics in that
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TruncateMod'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    the result here is consistent with a truncating divide. E.g. <c>truncate(x / y) *
        ///    y + truncate_mod(x, y) = x</c>.
        ///    
        ///    *NOTE*: <c>TruncateMod</c> supports broadcasting. More about broadcasting
        ///    [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
        /// </remarks>
        public static Tensor truncate_mod (Tensor x, Tensor y, string name = "TruncateMod")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["y"] = y;
            var op = _op_def_lib._apply_op_helper("TruncateMod", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Outputs random values from a truncated normal distribution.
        /// </summary>
        /// <param name="shape">
        ///    The shape of the output tensor.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TruncatedNormal'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The type of the output.
        /// </param>
        /// <param name="seed">
        ///    If either <c>seed</c> or <c>seed2</c> are set to be non-zero, the random number
        ///    generator is seeded by the given seed.  Otherwise, it is seeded by a
        ///    random seed.
        /// </param>
        /// <param name="seed2">
        ///    A second seed to avoid seed collision.
        /// </param>
        /// <returns>
        ///    A tensor of the specified shape filled with random truncated normal
        ///    values.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The generated values follow a normal distribution with mean 0 and standard
        ///    deviation 1, except that values whose magnitude is more than 2 standard
        ///    deviations from the mean are dropped and re-picked.
        /// </remarks>
        public static Tensor truncated_normal (Tensor shape, TF_DataType dtype, int? seed = null, int? seed2 = null, string name = "TruncatedNormal")
        {
            var dict = new Dictionary<string, object>();
            dict["shape"] = shape;
            dict["dtype"] = dtype;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("TruncatedNormal", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Perform batches of RPC requests.
        /// </summary>
        /// <param name="address">
        ///    <c>0-D</c> or <c>1-D</c>.  The address (i.e. host_name:port) of the RPC server.
        ///    If this tensor has more than 1 element, then multiple parallel rpc requests
        ///    are sent.  This argument broadcasts with <c>method</c> and <c>request</c>.
        /// </param>
        /// <param name="method">
        ///    <c>0-D</c> or <c>1-D</c>.  The method address on the RPC server.
        ///    If this tensor has more than 1 element, then multiple parallel rpc requests
        ///    are sent.  This argument broadcasts with <c>address</c> and <c>request</c>.
        /// </param>
        /// <param name="request">
        ///    <c>0-D</c> or <c>1-D</c>.  Serialized proto strings: the rpc request argument.
        ///    If this tensor has more than 1 element, then multiple parallel rpc requests
        ///    are sent.  This argument broadcasts with <c>address</c> and <c>method</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'TryRpc'.
        /// </param>
        /// <param name="protocol">
        ///    RPC protocol to use.  Empty string means use the default protocol.
        ///    Options include 'grpc'.
        /// </param>
        /// <param name="fail_fast">
        ///    <c>boolean</c>. If <c>true</c> (default), then failures to connect
        ///    (i.e., the server does not immediately respond) cause an RPC failure.
        /// </param>
        /// <param name="timeout_in_ms">
        ///    <c>int</c>. If <c>0</c> (default), then the kernel will run the RPC
        ///    request and only time out if the RPC deadline passes or the session times out.
        ///    If this value is greater than <c>0</c>, then the op will raise an exception if
        ///    the RPC takes longer than <c>timeout_in_ms</c>.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    response : Same shape as <c>request</c>. Serialized proto strings: the rpc responses.
        ///    status_code : Same shape as <c>request</c>.  Values correspond to tensorflow Status enum codes.
        ///    status_message : Same shape as <c>request</c>.  Values correspond to Status messages
        ///    returned from the RPC calls.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    This op asynchronously performs either a single RPC request, or a batch
        ///    of requests.  RPC requests are defined by three main parameters:
        ///    
        ///    - <c>address</c> (the host+port or BNS address of the request)
        ///    - <c>method</c> (the method name for the request)
        ///    - <c>request</c> (the serialized proto string, or vector of strings,
        ///    of the RPC request argument).
        ///    
        ///    For example, if you have an RPC service running on port localhost:2345,
        ///    and its interface is configured with the following proto declaration:
        ///    
        ///   <code>
        ///    service MyService {
        ///    rpc MyMethod(MyRequestProto) returns (MyResponseProto) {
        ///    }
        ///    };
        ///   </code>
        ///    
        ///    then call this op with arguments:
        ///    
        ///   <code>
        ///    address = "localhost:2345"
        ///    method = "MyService/MyMethod"
        ///   </code>
        ///    
        ///    The <c>request</c> tensor is a string tensor representing serialized <c>MyRequestProto</c>
        ///    strings; and the output string tensor <c>response</c> will have the same shape
        ///    and contain (upon successful completion) corresponding serialized
        ///    <c>MyResponseProto</c> strings.
        ///    
        ///    For example, to send a single, empty, <c>MyRequestProto</c>, call
        ///    this op with <c>request = ""</c>.  To send 5 **parallel** empty requests,
        ///    call this op with <c>request = ["", "", "", "", ""]</c>.
        ///    
        ///    More generally, one can create a batch of <c>MyRequestProto</c> serialized protos
        ///    from regular batched tensors using the <c>encode_proto</c> op, and convert
        ///    the response <c>MyResponseProto</c> serialized protos to batched tensors
        ///    using the <c>decode_proto</c> op.
        ///    
        ///    **NOTE** Working with serialized proto strings is faster than instantiating
        ///    actual proto objects in memory, so no performance degradation is expected
        ///    compared to writing custom kernels for this workflow.
        ///    
        ///    Unlike the standard <c>Rpc</c> op, if the connection fails or the remote worker
        ///    returns an error status, this op does **not** reraise the exception.
        ///    Instead, the <c>status_code</c> and <c>status_message</c> entry for the corresponding RPC
        ///    call is set with the error returned from the RPC call.  The <c>response</c> tensor
        ///    will contain valid response values for those minibatch entries whose RPCs did
        ///    not fail; the rest of the entries will have empty strings.
        /// </remarks>
        public static (Tensor response, Tensor status_code, Tensor status_message) try_rpc (Tensor address, Tensor method, Tensor request, string protocol = null, bool? fail_fast = null, int? timeout_in_ms = null, string name = "TryRpc")
        {
            var dict = new Dictionary<string, object>();
            dict["address"] = address;
            dict["method"] = method;
            dict["request"] = request;
            if (protocol != null)
                dict["protocol"] = protocol;
            if (fail_fast.HasValue)
                dict["fail_fast"] = fail_fast.Value;
            if (timeout_in_ms.HasValue)
                dict["timeout_in_ms"] = timeout_in_ms.Value;
            var op = _op_def_lib._apply_op_helper("TryRpc", name: name, keywords: dict);
            int _idx = 0;
            var response = op.outputs[_idx++];
            var status_code = op.outputs[_idx++];
            var status_message = op.outputs[_idx++];
            return (response, status_code, status_message);
        }

        /// <summary>
        ///    Reverses the operation of Batch for a single output Tensor.
        /// </summary>
        /// <param name="batched_tensor">
        /// </param>
        /// <param name="batch_index">
        /// </param>
        /// <param name="id">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Unbatch'.
        /// </param>
        /// <param name="timeout_micros">
        ///    Optional argument
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    An instance of Unbatch either receives an empty batched_tensor, in which case it
        ///    asynchronously waits until the values become available from a concurrently
        ///    running instance of Unbatch with the same container and shared_name, or receives
        ///    a non-empty batched_tensor in which case it finalizes all other concurrently
        ///    running instances and outputs its own element from the batch.
        ///    
        ///    batched_tensor: The possibly transformed output of Batch. The size of the first
        ///    dimension should remain unchanged by the transformations for the operation to
        ///    work.
        ///    batch_index: The matching batch_index obtained from Batch.
        ///    id: The id scalar emitted by Batch.
        ///    unbatched_tensor: The Tensor corresponding to this execution.
        ///    timeout_micros: Maximum amount of time (in microseconds) to wait to receive the
        ///    batched input tensor associated with a given invocation of the op.
        ///    container: Container to control resource sharing.
        ///    shared_name: Instances of Unbatch with the same container and shared_name are
        ///    assumed to possibly belong to the same batch. If left empty, the op name will
        ///    be used as the shared name.
        /// </remarks>
        public static Tensor unbatch (Tensor batched_tensor, Tensor batch_index, Tensor id, int timeout_micros, string container = null, string shared_name = null, string name = "Unbatch")
        {
            var dict = new Dictionary<string, object>();
            dict["batched_tensor"] = batched_tensor;
            dict["batch_index"] = batch_index;
            dict["id"] = id;
            dict["timeout_micros"] = timeout_micros;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("Unbatch", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A dataset that splits the elements of its input into multiple elements.
        /// </summary>
        /// <param name="input_dataset">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'UnbatchDataset'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor unbatch_dataset (Tensor input_dataset, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "UnbatchDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["input_dataset"] = input_dataset;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("UnbatchDataset", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Gradient of Unbatch.
        /// </summary>
        /// <param name="original_input">
        /// </param>
        /// <param name="batch_index">
        /// </param>
        /// <param name="grad">
        /// </param>
        /// <param name="id">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'UnbatchGrad'.
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Acts like Batch but using the given batch_index index of batching things as they
        ///    become available. This ensures that the gradients are propagated back in the
        ///    same session which did the forward pass.
        ///    
        ///    original_input: The input to the Unbatch operation this is the gradient of.
        ///    batch_index: The batch_index given to the Unbatch operation this is the gradient
        ///    of.
        ///    grad: The downstream gradient.
        ///    id: The id scalar emitted by Batch.
        ///    batched_grad: The return value, either an empty tensor or the batched gradient.
        ///    container: Container to control resource sharing.
        ///    shared_name: Instances of UnbatchGrad with the same container and shared_name
        ///    are assumed to possibly belong to the same batch. If left empty, the op name
        ///    will be used as the shared name.
        /// </remarks>
        public static Tensor unbatch_grad (Tensor original_input, Tensor batch_index, Tensor grad, Tensor id, string container = null, string shared_name = null, string name = "UnbatchGrad")
        {
            var dict = new Dictionary<string, object>();
            dict["original_input"] = original_input;
            dict["batch_index"] = batch_index;
            dict["grad"] = grad;
            dict["id"] = id;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("UnbatchGrad", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Generates labels for candidate sampling with a uniform distribution.
        /// </summary>
        /// <param name="true_classes">
        ///    A batch_size * num_true matrix, in which each row contains the
        ///    IDs of the num_true target_classes in the corresponding original label.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'UniformCandidateSampler'.
        /// </param>
        /// <param name="num_true">
        ///    Optional argument
        ///    Number of true labels per context.
        /// </param>
        /// <param name="num_sampled">
        ///    Optional argument
        ///    Number of candidates to randomly sample.
        /// </param>
        /// <param name="unique">
        ///    Optional argument
        ///    If unique is true, we sample with rejection, so that all sampled
        ///    candidates in a batch are unique. This requires some approximation to
        ///    estimate the post-rejection sampling probabilities.
        /// </param>
        /// <param name="range_max">
        ///    Optional argument
        ///    The sampler will sample integers from the interval [0, range_max).
        /// </param>
        /// <param name="seed">
        ///    If either seed or seed2 are set to be non-zero, the random number
        ///    generator is seeded by the given seed.  Otherwise, it is seeded by a
        ///    random seed.
        /// </param>
        /// <param name="seed2">
        ///    An second seed to avoid seed collision.
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    sampled_candidates : A vector of length num_sampled, in which each element is
        ///    the ID of a sampled candidate.
        ///    true_expected_count : A batch_size * num_true matrix, representing
        ///    the number of times each candidate is expected to occur in a batch
        ///    of sampled candidates. If unique=true, then this is a probability.
        ///    sampled_expected_count : A vector of length num_sampled, for each sampled
        ///    candidate representing the number of times the candidate is expected
        ///    to occur in a batch of sampled candidates.  If unique=true, then this is a
        ///    probability.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    See explanations of candidate sampling and the data formats at
        ///    go/candidate-sampling.
        ///    
        ///    For each batch, this op picks a single set of sampled candidate labels.
        ///    
        ///    The advantages of sampling candidates per-batch are simplicity and the
        ///    possibility of efficient dense matrix multiplication. The disadvantage is that
        ///    the sampled candidates must be chosen independently of the context and of the
        ///    true labels.
        /// </remarks>
        public static (Tensor sampled_candidates, Tensor true_expected_count, Tensor sampled_expected_count) uniform_candidate_sampler (Tensor true_classes, int num_true, int num_sampled, bool unique, int range_max, int? seed = null, int? seed2 = null, string name = "UniformCandidateSampler")
        {
            var dict = new Dictionary<string, object>();
            dict["true_classes"] = true_classes;
            dict["num_true"] = num_true;
            dict["num_sampled"] = num_sampled;
            dict["unique"] = unique;
            dict["range_max"] = range_max;
            if (seed.HasValue)
                dict["seed"] = seed.Value;
            if (seed2.HasValue)
                dict["seed2"] = seed2.Value;
            var op = _op_def_lib._apply_op_helper("UniformCandidateSampler", name: name, keywords: dict);
            int _idx = 0;
            var sampled_candidates = op.outputs[_idx++];
            var true_expected_count = op.outputs[_idx++];
            var sampled_expected_count = op.outputs[_idx++];
            return (sampled_candidates, true_expected_count, sampled_expected_count);
        }

        /// <summary>
        ///    Finds unique elements in a 1-D tensor.
        /// </summary>
        /// <param name="x">
        ///    1-D.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Unique'.
        /// </param>
        /// <param name="out_idx">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    y : 1-D.
        ///    idx : 1-D.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    This operation returns a tensor <c>y</c> containing all of the unique elements of <c>x</c>
        ///    sorted in the same order that they occur in <c>x</c>. This operation also returns a
        ///    tensor <c>idx</c> the same size as <c>x</c> that contains the index of each value of <c>x</c>
        ///    in the unique output <c>y</c>. In other words:
        ///    
        ///    <c>y[idx[i]] = x[i] for i in [0, 1,...,rank(x) - 1]</c>
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # tensor 'x' is [1, 1, 2, 4, 4, 4, 7, 8, 8]
        ///    y, idx = unique(x)
        ///    y ==&amp;gt; [1, 2, 4, 7, 8]
        ///    idx ==&amp;gt; [0, 0, 1, 2, 2, 2, 3, 4, 4]
        ///   </code>
        /// </remarks>
        public static (Tensor y, Tensor idx) unique (Tensor x, TF_DataType? out_idx = null, string name = "Unique")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            if (out_idx.HasValue)
                dict["out_idx"] = out_idx.Value;
            var op = _op_def_lib._apply_op_helper("Unique", name: name, keywords: dict);
            int _idx = 0;
            var y = op.outputs[_idx++];
            var idx = op.outputs[_idx++];
            return (y, idx);
        }

        /// <summary>
        ///    Finds unique elements along an axis of a tensor.
        /// </summary>
        /// <param name="x">
        ///    A <c>Tensor</c>.
        /// </param>
        /// <param name="axis">
        ///    A <c>Tensor</c> of type <c>int32</c> (default: None). The axis of the Tensor to
        ///    find the unique elements.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'UniqueV2'.
        /// </param>
        /// <param name="out_idx">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    y : A <c>Tensor</c>. Unique elements along the <c>axis</c> of <c>Tensor</c> x.
        ///    idx : A 1-D Tensor. Has the same type as x that contains the index of each
        ///    value of x in the output y.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    This operation either returns a tensor <c>y</c> containing unique elements
        ///    along the <c>axis</c> of a tensor. The returned unique elements is sorted
        ///    in the same order as they occur along <c>axis</c> in <c>x</c>.
        ///    This operation also returns a tensor <c>idx</c> that is the same size as
        ///    the number of the elements in <c>x</c> along the <c>axis</c> dimension. It
        ///    contains the index in the unique output <c>y</c>.
        ///    In other words, for an <c>1-D</c> tensor <c>x</c> with <c>axis = None:
        ///    
        ///    </c>y[idx[i]] = x[i] for i in [0, 1,...,rank(x) - 1]<c>
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # tensor 'x' is [1, 1, 2, 4, 4, 4, 7, 8, 8]
        ///    y, idx = unique(x)
        ///    y ==&amp;gt; [1, 2, 4, 7, 8]
        ///    idx ==&amp;gt; [0, 0, 1, 2, 2, 2, 3, 4, 4]
        ///   </code>
        ///    
        ///    For an </c>2-D<c> tensor </c>x<c> with </c>axis = 0<c>:
        ///    
        ///   <code>
        ///    # tensor 'x' is [[1, 0, 0],
        ///    #                [1, 0, 0],
        ///    #                [2, 0, 0]]
        ///    y, idx = unique(x, axis=0)
        ///    y ==&amp;gt; [[1, 0, 0],
        ///    [2, 0, 0]]
        ///    idx ==&amp;gt; [0, 0, 1]
        ///   </code>
        ///    
        ///    For an </c>2-D<c> tensor </c>x<c> with </c>axis = 1<c>:
        ///    
        ///   <code>
        ///    # tensor 'x' is [[1, 0, 0],
        ///    #                [1, 0, 0],
        ///    #                [2, 0, 0]]
        ///    y, idx = unique(x, axis=1)
        ///    y ==&amp;gt; [[1, 0],
        ///    [1, 0],
        ///    [2, 0]]
        ///    idx ==&amp;gt; [0, 1, 1]
        ///   </code>
        /// </remarks>
        public static (Tensor y, Tensor idx) unique_v2 (Tensor x, Tensor axis, TF_DataType? out_idx = null, string name = "UniqueV2")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["axis"] = axis;
            if (out_idx.HasValue)
                dict["out_idx"] = out_idx.Value;
            var op = _op_def_lib._apply_op_helper("UniqueV2", name: name, keywords: dict);
            int _idx = 0;
            var y = op.outputs[_idx++];
            var idx = op.outputs[_idx++];
            return (y, idx);
        }

        /// <summary>
        ///    Finds unique elements in a 1-D tensor.
        /// </summary>
        /// <param name="x">
        ///    1-D.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'UniqueWithCounts'.
        /// </param>
        /// <param name="out_idx">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    y : 1-D.
        ///    idx : 1-D.
        ///    count : 1-D.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    This operation returns a tensor <c>y</c> containing all of the unique elements of <c>x</c>
        ///    sorted in the same order that they occur in <c>x</c>. This operation also returns a
        ///    tensor <c>idx</c> the same size as <c>x</c> that contains the index of each value of <c>x</c>
        ///    in the unique output <c>y</c>. Finally, it returns a third tensor <c>count</c> that
        ///    contains the count of each element of <c>y</c> in <c>x</c>. In other words:
        ///    
        ///    <c>y[idx[i]] = x[i] for i in [0, 1,...,rank(x) - 1]</c>
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # tensor 'x' is [1, 1, 2, 4, 4, 4, 7, 8, 8]
        ///    y, idx, count = unique_with_counts(x)
        ///    y ==&amp;gt; [1, 2, 4, 7, 8]
        ///    idx ==&amp;gt; [0, 0, 1, 2, 2, 2, 3, 4, 4]
        ///    count ==&amp;gt; [2, 1, 3, 1, 2]
        ///   </code>
        /// </remarks>
        public static (Tensor y, Tensor idx, Tensor count) unique_with_counts (Tensor x, TF_DataType? out_idx = null, string name = "UniqueWithCounts")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            if (out_idx.HasValue)
                dict["out_idx"] = out_idx.Value;
            var op = _op_def_lib._apply_op_helper("UniqueWithCounts", name: name, keywords: dict);
            int _idx = 0;
            var y = op.outputs[_idx++];
            var idx = op.outputs[_idx++];
            var count = op.outputs[_idx++];
            return (y, idx, count);
        }

        /// <summary>
        ///    Finds unique elements along an axis of a tensor.
        /// </summary>
        /// <param name="x">
        ///    A <c>Tensor</c>.
        /// </param>
        /// <param name="axis">
        ///    A <c>Tensor</c> of type <c>int32</c> (default: None). The axis of the Tensor to
        ///    find the unique elements.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'UniqueWithCountsV2'.
        /// </param>
        /// <param name="out_idx">
        /// </param>
        /// <returns>
        ///    Returns a tuple with multiple values, as follows:
        ///    y : A <c>Tensor</c>. Unique elements along the <c>axis</c> of <c>Tensor</c> x.
        ///    idx : A 1-D Tensor. Has the same type as x that contains the index of each
        ///    value of x in the output y.
        ///    count : A 1-D Tensor. The count of each value of x in the output y.
        ///    The Operation can be fetched from any of the Tensorreturned in the tuple values, by fetching the Operation property.
        /// </returns>
        /// <remarks>
        ///    This operation either returns a tensor <c>y</c> containing unique elements
        ///    along the <c>axis</c> of a tensor. The returned unique elements is sorted
        ///    in the same order as they occur along <c>axis</c> in <c>x</c>.
        ///    This operation also returns a tensor <c>idx</c> and a tensor <c>count</c>
        ///    that are the same size as the number of the elements in <c>x</c> along the
        ///    <c>axis</c> dimension. The <c>idx</c> contains the index in the unique output <c>y</c>
        ///    and the <c>count</c> contains the count in the unique output <c>y</c>.
        ///    In other words, for an <c>1-D</c> tensor <c>x</c> with <c>axis = None:
        ///    
        ///    </c>y[idx[i]] = x[i] for i in [0, 1,...,rank(x) - 1]<c>
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # tensor 'x' is [1, 1, 2, 4, 4, 4, 7, 8, 8]
        ///    y, idx, count = unique_with_counts(x)
        ///    y ==&amp;gt; [1, 2, 4, 7, 8]
        ///    idx ==&amp;gt; [0, 0, 1, 2, 2, 2, 3, 4, 4]
        ///    count ==&amp;gt; [2, 1, 3, 1, 2]
        ///   </code>
        ///    
        ///    For an </c>2-D<c> tensor </c>x<c> with </c>axis = 0<c>:
        ///    
        ///   <code>
        ///    # tensor 'x' is [[1, 0, 0],
        ///    #                [1, 0, 0],
        ///    #                [2, 0, 0]]
        ///    y, idx, count = unique_with_counts(x, axis=0)
        ///    y ==&amp;gt; [[1, 0, 0],
        ///    [2, 0, 0]]
        ///    idx ==&amp;gt; [0, 0, 1]
        ///    count ==&amp;gt; [2, 1]
        ///   </code>
        ///    
        ///    For an </c>2-D<c> tensor </c>x<c> with </c>axis = 1<c>:
        ///    
        ///   <code>
        ///    # tensor 'x' is [[1, 0, 0],
        ///    #                [1, 0, 0],
        ///    #                [2, 0, 0]]
        ///    y, idx, count = unique_with_counts(x, axis=1)
        ///    y ==&amp;gt; [[1, 0],
        ///    [1, 0],
        ///    [2, 0]]
        ///    idx ==&amp;gt; [0, 1, 1]
        ///    count ==&amp;gt; [1, 2]
        ///   </code>
        /// </remarks>
        public static (Tensor y, Tensor idx, Tensor count) unique_with_counts_v2 (Tensor x, Tensor axis, TF_DataType? out_idx = null, string name = "UniqueWithCountsV2")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["axis"] = axis;
            if (out_idx.HasValue)
                dict["out_idx"] = out_idx.Value;
            var op = _op_def_lib._apply_op_helper("UniqueWithCountsV2", name: name, keywords: dict);
            int _idx = 0;
            var y = op.outputs[_idx++];
            var idx = op.outputs[_idx++];
            var count = op.outputs[_idx++];
            return (y, idx, count);
        }

        /// <summary>
        ///    Unpacks a given dimension of a rank-<c>R</c> tensor into <c>num</c> rank-<c>(R-1)</c> tensors.
        /// </summary>
        /// <param name="value">
        ///    1-D or higher, with <c>axis</c> dimension size equal to <c>num</c>.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Unpack'.
        /// </param>
        /// <param name="num">
        ///    Optional argument
        /// </param>
        /// <param name="axis">
        ///    Dimension along which to unpack.  Negative values wrap around, so the
        ///    valid range is <c>[-R, R)</c>.
        /// </param>
        /// <returns>
        ///    The list of tensors unpacked from <c>value</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Unpacks <c>num</c> tensors from <c>value</c> by chipping it along the <c>axis</c> dimension.
        ///    For example, given a tensor of shape <c>(A, B, C, D)</c>;
        ///    
        ///    If <c>axis == 0</c> then the i'th tensor in <c>output</c> is the slice <c>value[i, :, :, :]</c>
        ///    and each tensor in <c>output</c> will have shape <c>(B, C, D)</c>. (Note that the
        ///    dimension unpacked along is gone, unlike <c>split</c>).
        ///    
        ///    If <c>axis == 1</c> then the i'th tensor in <c>output</c> is the slice <c>value[:, i, :, :]</c>
        ///    and each tensor in <c>output</c> will have shape <c>(A, C, D)</c>.
        ///    Etc.
        ///    
        ///    This is the opposite of <c>pack</c>.
        /// </remarks>
        public static Tensor[] unpack (Tensor value, int num, int? axis = null, string name = "Unpack")
        {
            var dict = new Dictionary<string, object>();
            dict["value"] = value;
            dict["num"] = num;
            if (axis.HasValue)
                dict["axis"] = axis.Value;
            var op = _op_def_lib._apply_op_helper("Unpack", name: name, keywords: dict);
            int _idx = 0;
            var output = Enumerable.Range(0, op.OutputListLength("output")).Select(_ => op.outputs[_idx++]).ToArray();
            return (output);
        }

        /// <summary>
        ///    Converts a flat index or array of flat indices into a tuple of
        /// </summary>
        /// <param name="indices">
        ///    An 0-D or 1-D <c>int</c> Tensor whose elements are indices into the
        ///    flattened version of an array of dimensions dims.
        /// </param>
        /// <param name="dims">
        ///    An 1-D <c>int</c> Tensor. The shape of the array to use for unraveling
        ///    indices.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'UnravelIndex'.
        /// </param>
        /// <returns>
        ///    An 2-D (or 1-D if indices is 0-D) tensor where each row has the
        ///    same shape as the indices array.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    coordinate arrays.
        ///    
        ///    @compatibility(numpy)
        ///    Equivalent to np.unravel_index
        ///    @end_compatibility
        /// </remarks>
        public static Tensor unravel_index (Tensor indices, Tensor dims, string name = "UnravelIndex")
        {
            var dict = new Dictionary<string, object>();
            dict["indices"] = indices;
            dict["dims"] = dims;
            var op = _op_def_lib._apply_op_helper("UnravelIndex", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the maximum along segments of a tensor.
        /// </summary>
        /// <param name="data">
        /// </param>
        /// <param name="segment_ids">
        ///    A tensor whose shape is a prefix of <c>data.shape</c>.END
        ///    }
        ///    out_arg {
        ///    name: "output"
        ///    description: &amp;lt;&amp;lt;END
        ///    Has same shape as data, except for the first <c>segment_ids.rank</c>
        ///    dimensions, which are replaced with a single dimension which has size
        ///    <c>num_segments</c>.
        /// </param>
        /// <param name="num_segments">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'UnsortedSegmentMax'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Read
        ///    [the section on segmentation](https://tensorflow.org/api_guides/python/math_ops#Segmentation)
        ///    for an explanation of segments.
        ///    
        ///    This operator is similar to the unsorted segment sum operator found
        ///    [(here)](../../../api_docs/python/math_ops.md#UnsortedSegmentSum).
        ///    Instead of computing the sum over segments, it computes the maximum such that:
        ///    
        ///    \\(output_i = \max_{j...} data[j...]\\) where max is over tuples <c>j...</c> such
        ///    that <c>segment_ids[j...] == i</c>.
        ///    
        ///    If the maximum is empty for a given segment ID <c>i</c>, it outputs the smallest
        ///    possible value for the specific numeric type,
        ///    <c>output[i] = numeric_limits&amp;lt;T&amp;gt;::lowest()</c>.
        ///    
        ///    If the given segment ID <c>i</c> is negative, then the corresponding value is
        ///    dropped, and will not be included in the result.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src="https://www.tensorflow.org/images/UnsortedSegmentMax.png" alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Tensor unsorted_segment_max (Tensor data, Tensor segment_ids, Tensor num_segments, string name = "UnsortedSegmentMax")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            dict["segment_ids"] = segment_ids;
            dict["num_segments"] = num_segments;
            var op = _op_def_lib._apply_op_helper("UnsortedSegmentMax", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the minimum along segments of a tensor.
        /// </summary>
        /// <param name="data">
        /// </param>
        /// <param name="segment_ids">
        ///    A tensor whose shape is a prefix of <c>data.shape</c>.
        /// </param>
        /// <param name="num_segments">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'UnsortedSegmentMin'.
        /// </param>
        /// <returns>
        ///    Has same shape as data, except for the first <c>segment_ids.rank</c>
        ///    dimensions, which are replaced with a single dimension which has size
        ///    <c>num_segments</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Read
        ///    [the section on segmentation](https://tensorflow.org/api_guides/python/math_ops#segmentation)
        ///    for an explanation of segments.
        ///    
        ///    This operator is similar to the unsorted segment sum operator found
        ///    [(here)](../../../api_docs/python/math_ops.md#UnsortedSegmentSum).
        ///    Instead of computing the sum over segments, it computes the minimum such that:
        ///    
        ///    \\(output_i = \min_{j...} data_[j...]\\) where min is over tuples <c>j...</c> such
        ///    that <c>segment_ids[j...] == i</c>.
        ///    
        ///    If the minimum is empty for a given segment ID <c>i</c>, it outputs the largest
        ///    possible value for the specific numeric type,
        ///    <c>output[i] = numeric_limits&amp;lt;T&amp;gt;::max()</c>.
        ///    
        ///    If the given segment ID <c>i</c> is negative, then the corresponding value is
        ///    dropped, and will not be included in the result.
        /// </remarks>
        public static Tensor unsorted_segment_min (Tensor data, Tensor segment_ids, Tensor num_segments, string name = "UnsortedSegmentMin")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            dict["segment_ids"] = segment_ids;
            dict["num_segments"] = num_segments;
            var op = _op_def_lib._apply_op_helper("UnsortedSegmentMin", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the product along segments of a tensor.
        /// </summary>
        /// <param name="data">
        /// </param>
        /// <param name="segment_ids">
        ///    A tensor whose shape is a prefix of <c>data.shape</c>.
        /// </param>
        /// <param name="num_segments">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'UnsortedSegmentProd'.
        /// </param>
        /// <returns>
        ///    Has same shape as data, except for the first <c>segment_ids.rank</c>
        ///    dimensions, which are replaced with a single dimension which has size
        ///    <c>num_segments</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Read
        ///    [the section on segmentation](https://tensorflow.org/api_guides/python/math_ops#segmentation)
        ///    for an explanation of segments.
        ///    
        ///    This operator is similar to the unsorted segment sum operator found
        ///    [(here)](../../../api_docs/python/math_ops.md#UnsortedSegmentSum).
        ///    Instead of computing the sum over segments, it computes the product of all
        ///    entries belonging to a segment such that:
        ///    
        ///    \\(output_i = \prod_{j...} data[j...]\\) where the product is over tuples
        ///    <c>j...</c> such that <c>segment_ids[j...] == i</c>.
        ///    
        ///    If there is no entry for a given segment ID <c>i</c>, it outputs 1.
        ///    
        ///    If the given segment ID <c>i</c> is negative, then the corresponding value is
        ///    dropped, and will not be included in the result.
        /// </remarks>
        public static Tensor unsorted_segment_prod (Tensor data, Tensor segment_ids, Tensor num_segments, string name = "UnsortedSegmentProd")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            dict["segment_ids"] = segment_ids;
            dict["num_segments"] = num_segments;
            var op = _op_def_lib._apply_op_helper("UnsortedSegmentProd", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Computes the sum along segments of a tensor.
        /// </summary>
        /// <param name="data">
        /// </param>
        /// <param name="segment_ids">
        ///    A tensor whose shape is a prefix of <c>data.shape</c>.
        /// </param>
        /// <param name="num_segments">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'UnsortedSegmentSum'.
        /// </param>
        /// <returns>
        ///    Has same shape as data, except for the first <c>segment_ids.rank</c>
        ///    dimensions, which are replaced with a single dimension which has size
        ///    <c>num_segments</c>.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Read
        ///    [the section on segmentation](https://tensorflow.org/api_guides/python/math_ops#Segmentation)
        ///    for an explanation of segments.
        ///    
        ///    Computes a tensor such that
        ///    \\(output[i] = \sum_{j...} data[j...]\\) where the sum is over tuples <c>j...</c> such
        ///    that <c>segment_ids[j...] == i</c>.  Unlike <c>SegmentSum</c>, <c>segment_ids</c>
        ///    need not be sorted and need not cover all values in the full
        ///    range of valid values.
        ///    
        ///    If the sum is empty for a given segment ID <c>i</c>, <c>output[i] = 0</c>.
        ///    If the given segment ID <c>i</c> is negative, the value is dropped and will not be
        ///    added to the sum of the segment.
        ///    
        ///    <c>num_segments</c> should equal the number of distinct segment IDs.
        ///    
        ///    &amp;lt;div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;"&amp;gt;
        ///    &amp;lt;img style="width:100%" src="https://www.tensorflow.org/images/UnsortedSegmentSum.png" alt&amp;gt;
        ///    &amp;lt;/div&amp;gt;
        /// </remarks>
        public static Tensor unsorted_segment_sum (Tensor data, Tensor segment_ids, Tensor num_segments, string name = "UnsortedSegmentSum")
        {
            var dict = new Dictionary<string, object>();
            dict["data"] = data;
            dict["segment_ids"] = segment_ids;
            dict["num_segments"] = num_segments;
            var op = _op_def_lib._apply_op_helper("UnsortedSegmentSum", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Op is similar to a lightweight Dequeue.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Unstage'.
        /// </param>
        /// <param name="dtypes">
        ///    Optional argument
        /// </param>
        /// <param name="capacity">
        /// </param>
        /// <param name="memory_limit">
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The basic functionality is similar to dequeue with many fewer
        ///    capabilities and options.  This Op is optimized for performance.
        /// </remarks>
        public static Tensor[] unstage (TF_DataType[] dtypes, int? capacity = null, int? memory_limit = null, string container = null, string shared_name = null, string name = "Unstage")
        {
            var dict = new Dictionary<string, object>();
            dict["dtypes"] = dtypes;
            if (capacity.HasValue)
                dict["capacity"] = capacity.Value;
            if (memory_limit.HasValue)
                dict["memory_limit"] = memory_limit.Value;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("Unstage", name: name, keywords: dict);
            int _idx = 0;
            var values = Enumerable.Range(0, op.OutputListLength("values")).Select(_ => op.outputs[_idx++]).ToArray();
            return (values);
        }

        /// <summary>
        ///    Creates a handle to a Variable resource.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'VarHandleOp'.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    the type of this variable. Must agree with the dtypes
        ///    of all ops using this variable.
        /// </param>
        /// <param name="shape">
        ///    Optional argument
        ///    The (possibly partially specified) shape of this variable.
        /// </param>
        /// <param name="container">
        ///    the container this variable is placed in.
        /// </param>
        /// <param name="shared_name">
        ///    the name by which this variable is referred to.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor var_handle_op (TF_DataType dtype, TensorShape shape, string container = null, string shared_name = null, string name = "VarHandleOp")
        {
            var dict = new Dictionary<string, object>();
            dict["dtype"] = dtype;
            dict["shape"] = shape;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("VarHandleOp", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Checks whether a resource handle-based variable has been initialized.
        /// </summary>
        /// <param name="resource">
        ///    the input resource handle.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'VarIsInitializedOp'.
        /// </param>
        /// <returns>
        ///    a scalar boolean which is true if the variable has been
        ///    initialized.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor var_is_initialized_op (Tensor resource, string name = "VarIsInitializedOp")
        {
            var dict = new Dictionary<string, object>();
            dict["resource"] = resource;
            var op = _op_def_lib._apply_op_helper("VarIsInitializedOp", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Use VariableV2 instead.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Variable'.
        /// </param>
        /// <param name="shape">
        ///    Optional argument
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        /// </param>
        /// <param name="container">
        /// </param>
        /// <param name="shared_name">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor variable (TensorShape shape, TF_DataType dtype, string container = null, string shared_name = null, string name = "Variable")
        {
            var dict = new Dictionary<string, object>();
            dict["shape"] = shape;
            dict["dtype"] = dtype;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("Variable", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns the shape of the variable pointed to by <c>resource</c>.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'VariableShape'.
        /// </param>
        /// <param name="out_type">
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation returns a 1-D integer tensor representing the shape of <c>input</c>.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # 't' is [[[1, 1, 1], [2, 2, 2]], [[3, 3, 3], [4, 4, 4]]]
        ///    shape(t) ==&amp;gt; [2, 2, 3]
        ///   </code>
        /// </remarks>
        public static Tensor variable_shape (Tensor input, TF_DataType? out_type = null, string name = "VariableShape")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            if (out_type.HasValue)
                dict["out_type"] = out_type.Value;
            var op = _op_def_lib._apply_op_helper("VariableShape", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Holds state in the form of a tensor that persists across steps.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'VariableV2'.
        /// </param>
        /// <param name="shape">
        ///    Optional argument
        ///    The shape of the variable tensor.
        /// </param>
        /// <param name="dtype">
        ///    Optional argument
        ///    The type of elements in the variable tensor.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this variable is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this variable is named in the given bucket
        ///    with this shared_name. Otherwise, the node name is used instead.
        /// </param>
        /// <returns>
        ///    A reference to the variable tensor.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Outputs a ref to the tensor state so it may be read or modified.
        ///    TODO(zhifengc/mrry): Adds a pointer to a more detail document
        ///    about sharing states in tensorflow.
        /// </remarks>
        public static Tensor variable_v2 (TensorShape shape, TF_DataType dtype, string container = null, string shared_name = null, string name = "VariableV2")
        {
            var dict = new Dictionary<string, object>();
            dict["shape"] = shape;
            dict["dtype"] = dtype;
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("VariableV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Returns locations of nonzero / true values in a tensor.
        /// </summary>
        /// <param name="input">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Where'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    This operation returns the coordinates of true elements in <c>condition</c>. The
        ///    coordinates are returned in a 2-D tensor where the first dimension (rows)
        ///    represents the number of true elements, and the second dimension (columns)
        ///    represents the coordinates of the true elements. Keep in mind, the shape of
        ///    the output tensor can vary depending on how many true values there are in
        ///    <c>condition</c>. Indices are output in row-major order.
        ///    
        ///    For example:
        ///    
        ///   <code>
        ///    # 'input' tensor is [[True, False]
        ///    #                    [True, False]]
        ///    # 'input' has two true values, so output has two coordinates.
        ///    # 'input' has rank of 2, so coordinates have two indices.
        ///    where(input) ==&amp;gt; [[0, 0],
        ///    [1, 0]]
        ///    
        ///    # <c>condition</c> tensor is [[[True, False]
        ///    #                     [True, False]]
        ///    #                    [[False, True]
        ///    #                     [False, True]]
        ///    #                    [[False, False]
        ///    #                     [False, True]]]
        ///    # 'input' has 5 true values, so output has 5 coordinates.
        ///    # 'input' has rank of 3, so coordinates have three indices.
        ///    where(input) ==&amp;gt; [[0, 0, 0],
        ///    [0, 1, 0],
        ///    [1, 0, 1],
        ///    [1, 1, 1],
        ///    [2, 1, 1]]
        ///    
        ///    # <c>condition</c> tensor is [[[1.5,  0.0]
        ///    #                     [-0.5, 0.0]]
        ///    #                    [[0.0,  0.25]
        ///    #                     [0.0,  0.75]]
        ///    #                    [[0.0,  0.0]
        ///    #                     [0.0,  0.01]]]
        ///    # 'input' has 5 nonzero values, so output has 5 coordinates.
        ///    # 'input' has rank of 3, so coordinates have three indices.
        ///    where(input) ==&amp;gt; [[0, 0, 0],
        ///    [0, 1, 0],
        ///    [1, 0, 1],
        ///    [1, 1, 1],
        ///    [2, 1, 1]]
        ///    
        ///    # <c>condition</c> tensor is [[[1.5 + 0.0j, 0.0  + 0.0j]
        ///    #                     [0.0 + 0.5j, 0.0  + 0.0j]]
        ///    #                    [[0.0 + 0.0j, 0.25 + 1.5j]
        ///    #                     [0.0 + 0.0j, 0.75 + 0.0j]]
        ///    #                    [[0.0 + 0.0j, 0.0  + 0.0j]
        ///    #                     [0.0 + 0.0j, 0.01 + 0.0j]]]
        ///    # 'input' has 5 nonzero magnitude values, so output has 5 coordinates.
        ///    # 'input' has rank of 3, so coordinates have three indices.
        ///    where(input) ==&amp;gt; [[0, 0, 0],
        ///    [0, 1, 0],
        ///    [1, 0, 1],
        ///    [1, 1, 1],
        ///    [2, 1, 1]]
        ///   </code>
        /// </remarks>
        public static Tensor where (Tensor input, string name = "Where")
        {
            var dict = new Dictionary<string, object>();
            dict["input"] = input;
            var op = _op_def_lib._apply_op_helper("Where", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A Reader that outputs the entire contents of a file as a value.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'WholeFileReader'.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this reader is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this reader is named in the given bucket
        ///    with this shared_name. Otherwise, the node name is used instead.
        /// </param>
        /// <returns>
        ///    The handle to reference the Reader.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    To use, enqueue filenames in a Queue.  The output of ReaderRead will
        ///    be a filename (key) and the contents of that file (value).
        /// </remarks>
        public static Tensor whole_file_reader (string container = null, string shared_name = null, string name = "WholeFileReader")
        {
            var dict = new Dictionary<string, object>();
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("WholeFileReader", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    A Reader that outputs the entire contents of a file as a value.
        /// </summary>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'WholeFileReaderV2'.
        /// </param>
        /// <param name="container">
        ///    If non-empty, this reader is placed in the given container.
        ///    Otherwise, a default container is used.
        /// </param>
        /// <param name="shared_name">
        ///    If non-empty, this reader is named in the given bucket
        ///    with this shared_name. Otherwise, the node name is used instead.
        /// </param>
        /// <returns>
        ///    The handle to reference the Reader.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    To use, enqueue filenames in a Queue.  The output of ReaderRead will
        ///    be a filename (key) and the contents of that file (value).
        /// </remarks>
        public static Tensor whole_file_reader_v2 (string container = null, string shared_name = null, string name = "WholeFileReaderV2")
        {
            var dict = new Dictionary<string, object>();
            if (container != null)
                dict["container"] = container;
            if (shared_name != null)
                dict["shared_name"] = shared_name;
            var op = _op_def_lib._apply_op_helper("WholeFileReaderV2", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Worker heartbeat op.
        /// </summary>
        /// <param name="request">
        ///    A string tensor containing a serialized WorkerHeartbeatRequest
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'WorkerHeartbeat'.
        /// </param>
        /// <returns>
        ///    A string tensor containing a serialized WorkerHeartbeatResponse
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    Heartbeats may be sent periodically to indicate the coordinator is still active,
        ///    to retrieve the current worker status and to expedite shutdown when necessary.
        /// </remarks>
        public static Tensor worker_heartbeat (Tensor request, string name = "WorkerHeartbeat")
        {
            var dict = new Dictionary<string, object>();
            dict["request"] = request;
            var op = _op_def_lib._apply_op_helper("WorkerHeartbeat", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Writes contents to the file at input filename. Creates file and recursively
        /// </summary>
        /// <param name="filename">
        ///    scalar. The name of the file to which we write the contents.
        /// </param>
        /// <param name="contents">
        ///    scalar. The content to be written to the output file.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'WriteFile'.
        /// </param>
        /// <returns>
        ///    Returns the description of the operation
        /// </returns>
        /// <remarks>
        ///    creates directory if not existing.
        /// </remarks>
        public static Operation write_file (Tensor filename, Tensor contents, string name = "WriteFile")
        {
            var dict = new Dictionary<string, object>();
            dict["filename"] = filename;
            dict["contents"] = contents;
            var op = _op_def_lib._apply_op_helper("WriteFile", name: name, keywords: dict);
            return op;
        }

        /// <summary>
        ///    Returns a tensor of zeros with the same shape and type as x.
        /// </summary>
        /// <param name="x">
        ///    a tensor of type T.
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ZerosLike'.
        /// </param>
        /// <returns>
        ///    a tensor of the same shape and type as x but filled with zeros.
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor zeros_like (Tensor x, string name = "ZerosLike")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            var op = _op_def_lib._apply_op_helper("ZerosLike", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Compute the Hurwitz zeta function \\(\zeta(x, q)\\).
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="q">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'Zeta'.
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        /// <remarks>
        ///    The Hurwitz zeta function is defined as:
        ///    
        ///    
        ///    \\(\zeta(x, q) = \sum_{n=0}^{\infty} (q + n)^{-x}\\)
        /// </remarks>
        public static Tensor zeta (Tensor x, Tensor q, string name = "Zeta")
        {
            var dict = new Dictionary<string, object>();
            dict["x"] = x;
            dict["q"] = q;
            var op = _op_def_lib._apply_op_helper("Zeta", name: name, keywords: dict);
            return op.output;
        }

        /// <summary>
        ///    Creates a dataset that zips together <c>input_datasets</c>.
        /// </summary>
        /// <param name="input_datasets">
        /// </param>
        /// <param name="name">
        /// If specified, the created operation in the graph will be this one, otherwise it will be named 'ZipDataset'.
        /// </param>
        /// <param name="output_types">
        ///    Optional argument
        /// </param>
        /// <param name="output_shapes">
        ///    Optional argument
        /// </param>
        /// <returns>
        ///    The Operation can be fetched from the resulting Tensor, by fetching the Operation property from the result.
        /// </returns>
        public static Tensor zip_dataset (Tensor[] input_datasets, TF_DataType[] output_types, TensorShape[] output_shapes, string name = "ZipDataset")
        {
            var dict = new Dictionary<string, object>();
            dict["input_datasets"] = input_datasets;
            dict["output_types"] = output_types;
            dict["output_shapes"] = output_shapes;
            var op = _op_def_lib._apply_op_helper("ZipDataset", name: name, keywords: dict);
            return op.output;
        }
    }
}
