title: Replacing placeholder for tensorflow v2
body: <p>For my project, I need to convert a directed graph into a tensorflow implementation of the graph as if it was a neural network. In tensorflow version 1, I could just define all of my inputs as placeholders and then just generate the dataflow graph for the outputs using a breadthfirst search of the graph. Then I would just feed in my inputs using a feed_dict. However, in TensorFlow v2.0 they have decided to do away with placeholders entirely.</p>
  
  <p>How would I make a tf.function for each graph that takes in a variable amount of inputs and returns a variable amount of outputs without using a placeholder?</p>
  
  <p>I want to generate a tf.function like this that works for an arbitrary acyclic directed graph so that I can take advantage of tensorflow GPU support to run the graph feed forward a few thousand times in a row after I have generated it.</p>
  
  <hr>
  
  <p>Edit for code example:</p>
  
  <p>My graph is defined as a dictionary. Each key represents a node and has a corresponding value of another dictionary specifying incoming and outgoing links with weights.</p>
  
  <pre class="lang-py prettyprint-override"><code>{
      "A": {
          "incoming": [("B", 2), ("C", -1)],
          "outgoing": [("D", 3)]
      }
  }
  </code></pre>
  
  <p>I have omitted the entries for B,C, and D for brevity.
  Here is how I would construct the code I want in tensorflow v1.0 where inputs is just a list of key values that are strictly inputs to the graph</p>
  
  <pre class="lang-py prettyprint-override"><code>def construct_graph(graph_dict, inputs, outputs):
      queue = inputs[:]
      make_dict = {}
      for key, val in graph_dict.items():
          if key in inputs:
              make_dict[key] = tf.placeholder(tf.float32, name=key)
          else:
              make_dict[key] = None
      # Breadth-First search of graph starting from inputs
      while len(queue) != 0:
          cur = graph_dict[queue[0]]
          for outg in cur["outgoing"]:
              if make_dict[outg[0]]: # If discovered node, do add/multiply operation
                  make_dict[outg[0]] = tf.add(make_dict[outg[0]], tf.multiply(outg[1], make_dict[queue[0]]))
              else: # If undiscovered node, input is just coming in multiplied and add outgoing to queue
                  make_dict[outg[0]] = tf.multiply(make_dict[queue[0]], outg[1])
                  for outgo in graph_dict[outg[0]]["outgoing"]:
                      queue.append(outgo[0])
          queue.pop(0)
      # Returns one data graph for each output
      return [make_dict[x] for x in outputs]
  </code></pre>
  
  <p>I would then be able to run the outputs many times as they are simply graphs with placeholders that I would provide a feed_dict for.</p>
  
  <p>Obviously, this is not the intended way in TensorFlow v2.0 as they seem to strongly discourage the use of placeholders in this new version.</p>
  
  <p>The point is that I only have to do this preprocessing for a graph once, as it returns a datagraph which is independent of the graph_dict definition.</p>