def _plan_distribute(self):
        """
        * **Source/ Dest:** One source to many destinations
        * **Volume:** Single volume or List of volumes is acceptable. This list
                      should be same length as destinations
        * **Behavior with transfer options:**

            - New_tip: can be either NEVER or ONCE
                       (ALWAYS will fallback to ONCE)
            - Air_gap: if specified, will be performed after every aspirate and
                       also in-between dispenses (to keep air gap while moving
                       between wells)
            - Blow_out: can be performed at the end of distribute (after mix,
                        before touch_tip) at the location specified. If there
                        is liquid present in the tip, blow_out will be
                        performed at either user-defined location or (default)
                        trash. If no liquid is supposed to be present in the
                        tip at the end of distribute, blow_out will be
                        performed at the last well the liquid was dispensed to
                        (if strategy is DEST_IF_EMPTY)
            - Touch_tip: can be performed after each aspirate and/or after
                         every dispense
            - Mix: can be performed before aspirate and/or after the last
                   dispense if there is no disposal volume (i.e. can be
                   performed only when the tip is supposed to be empty)

            Considering all options, the sequence of actions is:

            1. Going from source to dest1:
               *New Tip -> Mix -> Aspirate (with disposal volume) -> Air gap ->
               -> Touch tip -> Dispense air gap -> Dispense -> Mix if empty ->
               -> Blow out -> Touch tip -> Drop tip*
            2. Going from destn to destn+1:
               *.. Dispense air gap -> Dispense -> Touch tip -> Air gap ->
               .. Dispense air gap -> ...*

        """
        # TODO: decide whether default disposal vol for distribute should be
        # pipette min_vol or should we leave it to being 0 by default and
        # recommend users to specify a disposal vol when using distribute.
        # First method keeps distribute consistent with current behavior while
        # the other maintains consistency in default behaviors of all functions
        plan_iter = zip(self._volumes, self._dests)

        done = False
        current_xfer = next(plan_iter)
        if self._strategy.new_tip == types.TransferTipPolicy.ALWAYS:
            yield self._format_dict('pick_up_tip', kwargs=self._tip_opts)
        while not done:
            asp_grouped = []
            try:
                while (sum(a[0] for a in asp_grouped) +
                       self._strategy.disposal_volume +
                       self._strategy.air_gap +
                       current_xfer[0]) < self._instr.max_volume:
                    asp_grouped.append(current_xfer)
                    current_xfer = next(plan_iter)
            except StopIteration:
                done = True
            yield from self._aspirate_actions(sum(a[0] for a in asp_grouped) +
                                              self._strategy.disposal_volume,
                                              self._sources[0])
            for step in asp_grouped:
                yield from self._dispense_actions(step[0], step[1],
                                                  step is not asp_grouped[-1])
        yield from self._new_tip_action()