class_docstr: A FunctionGraph represents a subgraph bound by a set of input variables and
  a set of output variables, ie a subgraph that specifies a theano function.
  The inputs list should contain all the inputs on which the outputs depend.
  Variables of type Constant are not counted as inputs.
  
  The FunctionGraph supports the replace operation which allows to replace a
  variable in the subgraph by another, e.g. replace (x + x).out by (2
  * x).out. This is the basis for optimization in theano.
  
  This class is also responsible for verifying that a graph is valid
  (ie, all the dtypes and broadcast patterns are compatible with the
  way the the Variables are used) and for annotating the Variables with
  a .clients field that specifies which Apply nodes use the variable.
  The .clients field combined with the .owner field and the Apply nodes'
  .inputs field allows the graph to be traversed in both directions.
  
  It can also be extended with new features using
  FunctionGraph.attach_feature(<toolbox.Feature instance>).
  See toolbox.Feature for event types and documentation.
  Extra features allow the FunctionGraph to verify new properties of
  a graph as it is optimized.
  # TODO: are there other things features can do to the fgraph?
  
  Historically, the FunctionGraph was called an Env. Keep this in mind
  while reading out-of-date documentation, e-mail support threads, etc.
  
  The constructor creates a FunctionGraph which operates on the subgraph
  bound by the inputs and outputs sets.
  
  This class keeps a pointer to the inputs and outputs, and also modifies
  them.
  
  #TODO: document what variables are[not] set in the FunctionGraph when a
  feature is added via the constructor. How constructed is the
  FunctionGraph?
  
  Parameters
  ----------
  inputs
      Inputs nodes of the graph, usually declared by the user.
  outputs
      Outputs nodes of the graph.
  clone
      If true, we will clone the graph. This is useful to remove the constant
      cache problem.
  
  Notes
  -----
  The intermediate nodes between 'inputs' and 'outputs' are not explicitely
  passed.
class_docstr_tok: ["A","FunctionGraph","represents","a","subgraph","bound","by","a","set","of","input","variables","and","a","set","of","output","variables",",","ie","a","subgraph","that","specifies","a","theano","function",".","The","inputs","list","should","contain","all","the","inputs","on","which","the","outputs","depend",".","Variables","of","type","Constant","are","not","counted","as","inputs",".","The","FunctionGraph","supports","the","replace","operation","which","allows","to","replace","a","variable","in","the","subgraph","by","another",",","e.g",".","replace","(","x","+","x",")",".out","by","(","2","*","x",")",".out",".","This","is","the","basis","for","optimization","in","theano",".","This","class","is","also","responsible","for","verifying","that","a","graph","is","valid","(","ie",",","all","the","dtypes","and","broadcast","patterns","are","compatible","with","the","way","the","the","Variables","are","used",")","and","for","annotating","the","Variables","with","a",".clients","field","that","specifies","which","Apply","nodes","use","the","variable",".","The",".clients","field","combined","with","the",".owner","field","and","the","Apply","nodes'",".inputs","field","allows","the","graph","to","be","traversed","in","both","directions",".","It","can","also","be","extended","with","new","features","using","FunctionGraph.attach_feature","(","<","toolbox.Feature","instance",">",")",".","See","toolbox.Feature","for","event","types","and","documentation",".","Extra","features","allow","the","FunctionGraph","to","verify","new","properties","of","a","graph","as","it","is","optimized",".","#","TODO",":","are","there","other","things","features","can","do","to","the","fgraph","?","Historically",",","the","FunctionGraph","was","called","an","Env",".","Keep","this","in","mind","while","reading","out-of-date","documentation",",","e-mail","support","threads",",","etc",".","The","constructor","creates","a","FunctionGraph","which","operates","on","the","subgraph","bound","by","the","inputs","and","outputs","sets",".","This","class","keeps","a","pointer","to","the","inputs","and","outputs",",","and","also","modifies","them",".","#","TODO",":","document","what","variables","are","[","not","]","set","in","the","FunctionGraph","when","a","feature","is","added","via","the","constructor",".","How","constructed","is","the","FunctionGraph","?","Parameters","--","--","--","--","--","inputs","Inputs","nodes","of","the","graph",",","usually","declared","by","the","user",".","outputs","Outputs","nodes","of","the","graph",".","clone","If","true",",","we","will","clone","the","graph",".","This","is","useful","to","remove","the","constant","cache","problem",".","Notes","--","--","-","The","intermediate","nodes","between","'inputs","'","and","'outputs","'","are","not","explicitely","passed","."]
code: def __str__(self):
      return "[%s]" % ", ".join(
          graph.as_string(self.inputs, self.outputs)
      )
  
imports: from __future__ import absolute_import, print_function, division
  from collections import OrderedDict
  import time
  import theano
  from theano.gof import graph
  from theano.gof import utils
  from theano.gof import toolbox
  from theano import config
  from six import iteritems, itervalues
  from six.moves import StringIO
  from theano.gof.utils import get_variable_trace_string
  from theano.misc.ordered_set import OrderedSet
label_desc: Use image node_id 21 for calling the FunctionGraph obj's underlying member method code with example usage: obj.__str__() and returns: unknown