human
Complete the below
def as_op(itypes, otypes, infer_shape=None):

    ''''Decorator that converts a function into a basic Theano op that will call
    the supplied function as its implementation.
    It takes an optional infer_shape parameter that should be a callable with
    this signature:
    def infer_shape(node, input_shapes):
    return output_shapes
    Here `input_shapes` and `output_shapes` are lists of tuples that represent
    the shape of the corresponding inputs/outputs.
    This should not be used when performance is a concern since the very basic
    nature of the resulting Op may interfere with certain graph optimizations.
    Examples
    @as_op(itypes=[theano.tensor.fmatrix, theano.tensor.fmatrix],
    otypes=[theano.tensor.fmatrix])
    def numpy_dot(a, b):
    return numpy.dot(a, b)'
    '''

=====
What is a the Python code you requested?
assistant
#Here is the Python code you requested.
    if (not isinstance(itypes, (list, tuple))):
        itypes = [itypes]
    if any(((not isinstance(t, theano.Type)) for t in itypes)):
        raise TypeError('itypes    has    to    be    a    list    of    Theano    types')
    if (not isinstance(otypes, (list, tuple))):
        otypes = [otypes]
    if any(((not isinstance(t, theano.Type)) for t in otypes)):
        raise TypeError('otypes    has    to    be    a    list    of    Theano    types')
    itypes = list(itypes)
    otypes = list(otypes)
    if ((infer_shape is not None) and (not callable(infer_shape))):
        raise TypeError('infer_shape    needs    to    be    a    callable')
    def make_op(fn):
        return FromFunctionOp(fn, itypes, otypes, infer_shape)
    return make_op