code: def build_score_loss_and_gradients(inference, var_list):
      """Build loss function and gradients based on the score function
      estimator [@paisley2012variational].
  
      Computed by sampling from $q(z;\lambda)$ and evaluating the
      expectation using Monte Carlo sampling.
      """
      p_log_prob = [0.0] * inference.n_samples
      q_log_prob = [0.0] * inference.n_samples
      base_scope = tf.get_default_graph().unique_name("inference") + "/"
      for s in range(inference.n_samples):
          # Form dictionary in order to replace conditioning on prior or
          # observed variable with conditioning on a specific value.
          scope = base_scope + tf.get_default_graph().unique_name(
              "sample"
          )
          dict_swap = {}
          for x, qx in six.iteritems(inference.data):
              if isinstance(x, RandomVariable):
                  if isinstance(qx, RandomVariable):
                      qx_copy = copy(qx, scope=scope)
                      dict_swap[x] = qx_copy.value()
                  else:
                      dict_swap[x] = qx
  
          for z, qz in six.iteritems(inference.latent_vars):
              # Copy q(z) to obtain new set of posterior samples.
              qz_copy = copy(qz, scope=scope)
              dict_swap[z] = qz_copy.value()
              q_log_prob[s] += tf.reduce_sum(
                  inference.scale.get(z, 1.0)
                  * qz_copy.log_prob(tf.stop_gradient(dict_swap[z]))
              )
  
          for z in six.iterkeys(inference.latent_vars):
              z_copy = copy(z, dict_swap, scope=scope)
              p_log_prob[s] += tf.reduce_sum(
                  inference.scale.get(z, 1.0)
                  * z_copy.log_prob(dict_swap[z])
              )
  
          for x in six.iterkeys(inference.data):
              if isinstance(x, RandomVariable):
                  x_copy = copy(x, dict_swap, scope=scope)
                  p_log_prob[s] += tf.reduce_sum(
                      inference.scale.get(x, 1.0)
                      * x_copy.log_prob(dict_swap[x])
                  )
  
      p_log_prob = tf.stack(p_log_prob)
      q_log_prob = tf.stack(q_log_prob)
      reg_penalty = tf.reduce_sum(tf.losses.get_regularization_losses())
  
      if inference.logging:
          tf.summary.scalar(
              "loss/p_log_prob",
              tf.reduce_mean(p_log_prob),
              collections=[inference._summary_key],
          )
          tf.summary.scalar(
              "loss/q_log_prob",
              tf.reduce_mean(q_log_prob),
              collections=[inference._summary_key],
          )
          tf.summary.scalar(
              "loss/reg_penalty",
              reg_penalty,
              collections=[inference._summary_key],
          )
  
      losses = p_log_prob - q_log_prob
      loss = -(tf.reduce_mean(losses) - reg_penalty)
  
      q_rvs = list(six.itervalues(inference.latent_vars))
      q_vars = [
          v
          for v in var_list
          if len(get_descendants(tf.convert_to_tensor(v), q_rvs)) != 0
      ]
      q_grads = tf.gradients(
          -(
              tf.reduce_mean(q_log_prob * tf.stop_gradient(losses))
              - reg_penalty
          ),
          q_vars,
      )
      p_vars = [v for v in var_list if v not in q_vars]
      p_grads = tf.gradients(loss, p_vars)
      grads_and_vars = list(zip(q_grads, q_vars)) + list(
          zip(p_grads, p_vars)
      )
      return loss, grads_and_vars
  
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  import six
  import tensorflow
  from edward.inferences.variational_inference import VariationalInference
  from edward.models import RandomVariable
  from edward.util import copy, get_descendants
label_desc: Use image node_id 4 for calling a global function with example usage: build_score_loss_and_gradients(inference, var_list) and returns: loss,  grads_and_vars