**Description**

Currently `BaseOperator` and `XComArgs` implements the same logic of `__lshift__`, `__rshift__` and others "chain" operations (`>>`, `<<`). It seems resonable to abstract this logic into `TaskMixin` to introduce some DRYness especially because the new concept of `TaskGroup` will also implement the same methods.

**Use case / motivation**

Limit duplication of logic.

**Related Issues**

https://github.com/apache/airflow/pull/10827#issuecomment-691927501
#10153 

airflow/models/baseoperator.py
"""Getting the content of files for template_field / template_ext"""
        if self.template_ext:  
            for field in self.template_fields:
                content = getattr(self, field, None)
                if content is None:  
                    continue
                elif isinstance(content, str) and \
                        any(content.endswith(ext) for ext in self.template_ext):
                    env = self.get_template_env()
                    try:
                        setattr(self, field, env.loader.get_source(env, content)[0])
                    except Exception as e:  
                        self.log.exception(e)
                elif isinstance(content, list):
                    env = self.dag.get_template_env()
                    for i in range(len(content)):  
                        if isinstance(content[i], str) and \
                                any(content[i].endswith(ext) for ext in self.template_ext):
                            try:
                                content[i] = env.loader.get_source(env, content[i])[0]
                            except Exception as e:  
                                self.log.exception(e)
        self.prepare_template()
    @property
    def upstream_list(self) -> List["BaseOperator"]: