def figure_tensor(func, **tf_pyfunc_kwargs):
    '''Decorate matplotlib drawing routines.

    This dectorator is meant to decorate functions that return matplotlib
    figures. The decorated function has to have the following signature

        def decorated(*args, **kwargs) -> figure or iterable of figures
    
    where `*args` can be any positional argument and `**kwargs` are any
    keyword arguments. The decorated function returns a tensor of shape 
    `[NumFigures, Height, Width, 3]` of type `tf.uint8`. 
    
    The drawing code is invoked during running of TensorFlow sessions, 
    at a time when all positional tensor arguments have been evaluated 
    by the session. The decorated function is then passed the tensor values. 
    All non tensor arguments remain unchanged.
    '''

    name = tf_pyfunc_kwargs.pop('name', func.__name__)

    @wraps(func)
    def wrapper(*func_args, **func_kwargs):
        tf_args = PositionalTensorArgs(func_args)
        
        def pyfnc_callee(*tensor_values, **unused):
            try:
                figs = as_list(func(*tf_args.mix_args(tensor_values), **func_kwargs))
                for f in figs:
                    f.canvas.draw()
                return figure_buffer(figs)
            except Exception:
                print('-'*5 + 'tfmpl catched exception' + '-'*5)
                print(traceback.format_exc())                
                print('-'*20)
                raise

        return tf.py_func(pyfnc_callee, tf_args.tensor_args, tf.uint8, name=name, **tf_pyfunc_kwargs)
    return wrapper
Decorate matplotlib drawing routines.

    This dectorator is meant to decorate functions that return matplotlib
    figures. The decorated function has to have the following signature

        def decorated(*args, **kwargs) -> figure or iterable of figures
    
    where `*args` can be any positional argument and `**kwargs` are any
    keyword arguments. The decorated function returns a tensor of shape 
    `[NumFigures, Height, Width, 3]` of type `tf.uint8`. 
    
    The drawing code is invoked during running of TensorFlow sessions, 
    at a time when all positional tensor arguments have been evaluated 
    by the session. The decorated function is then passed the tensor values. 
    All non tensor arguments remain unchanged.