code: def testAddOpInMiddle(self):
      #  x1-->Relu--x2----------------->Add-->x4
      #                |                 |
      #                 -->Softmax-->x3-->
      #
      # Expected gradient graph:
      #
      #  x1_g<--ReluG<--x2_g<--Sum<------------<---------x4_g
      #                          |                       |
      #                           <--_x2_g_split_0<--SoftmaxG
      net = core.Net("test_net")
      net.Relu("x1", "x2")
      net.Softmax("x2", "x3")
      net.Add(["x2", "x3"], "x4")
      input_to_grad = net.AddGradientOperators({"x4": "x4_grad"})
      sum_op = net.Proto().op[-2]
      self.assertEqual(sum_op.input[0], "x2_grad")
      self.assertEqual(sum_op.input[1], "_x2_grad_autosplit_0")
      self.assertEqual(sum_op.output[0], "x2_grad")
      self.assertEqual(input_to_grad["x1"], "x1_grad")
  
imports: from hypothesis import given, settings
  import hypothesis.strategies
  import unittest
  from caffe2.proto import caffe2_pb2
  from caffe2.python import core, test_util, workspace
  from caffe2.python.core import CreateOperator, GradientRegistry, IR
  import numpy
label_desc: Use image node_id 1 for calling the TestGradientsAccumulationWithPassThroughGradients obj's underlying member method code with example usage: obj.testAddOpInMiddle() without return types