In case you need more control, here is another solution.
\documentclass{article}
\usepackage[dvipsnames]{xcolor}
\usepackage{ltxkeys}
\usepackage{multicol}
\makeatletter
% Keys:
\ltxkeys@declarekeys[GM]{bodystyle}[bdsty@]{%
cmd/body name/section/
\edef\bdsty@bodyname{\unexpanded{#1}}%
\ifltxkeys@dec\else
\ifblankTF{#1}{%
\@latexerr{Section body name can't be empty}\@ehd
}{%
\ifinsetTF{,#1,}{,chapter,section,subsection,paragraph,}{}{%
\@latexerr{Section body name not recognized}\@ehd
}%
}
\fi;
cmd/style list command//
\edef\bdsty@stylelistcommand{\unexpanded{#1}}%
\ifltxkeys@dec\else
\ifsingletokenFT{#1}{%
\@latexerr{Style command \detokenize{#1} isn't a single token}\@ehd
}{%
\ifescapedTF{#1}{%
\ifx#1\@undefined
\@latexerr{Style command \detokenize{#1} is undefined}\@ehd
\else
\ifx#1\@empty
\@latexerr{Style command \detokenize{#1} is empty}\@ehd
\fi
\fi
}{%
\@latexerr{Style command \detokenize{#1} isn't escaped}\@ehd
}%
}%
\fi;
cmd/repeated code//
\edef\bdsty@repeatedcode{\unexpanded{#1}};
cmd/exit code//
\csn@edef{bdsty@\bdsty@bodyname @exitcode}{\unexpanded{#1}};
}
% User commands:
% \newbodystyle[<keyval>]
\newcommand\newbodystyle[1][]{%
\ltxkeys@setkeys[GM]{bodystyle}{#1}%
\cptexpanded{%
\letcsntocsn{bodystyle@\bdsty@bodyname}{\bdsty@bodyname}%
\csn@def{\bdsty@bodyname}{%
\def\noexpand\n@wstylelist########1,########2\noexpand\newbodystyle{%
\expandcsonce\bdsty@repeatedcode{########1}%
\xdef\expandcsonce\bdsty@stylelistcommand{%
\unexpanded{\ifblankTF{####2}{}{\unexpanded{####2},}%
\unexpanded{####1}}%
}%
}%
\noexpand\xifinsetTF{,}{\noexpand\expandcsonce
\expandcsonce\bdsty@stylelistcommand}{%
\unexpanded{\expandafter\n@wstylelist}\expandcsonce
\bdsty@stylelistcommand\noexpand\newbodystyle
}{%
\unexpanded{\expandafter\n@wstylelist}\expandcsonce
\bdsty@stylelistcommand,\noexpand\newbodystyle
}%
\noexpand\usename{bodystyle@\bdsty@bodyname}%
}%
}%
}
% \restorebodystyle{<body name list>}
\newcommand*\restorebodystyle[1]{%
\cptdocommalist{#1}{%
\ifcsndefTF{bodystyle@##1}{%
\letcsntocsn{##1}{bodystyle@##1}%
\csname bdsty@##1@exitcode\endcsname
}{%
\@latexerr{Heading name '\detokenize{##1}' wasn't saved}\@ehd
}%
}%
}
\makeatother
% Example document:
\begin{document}
% Fonts:
\def\usefontpallete{%
\def\say{Current style: {\tt\detokenize\expandafter{\currstyle}}\par}%
\def\sayb{\def\currstyle{normal font}\normalfont}%
\def\style{\def\temp####1{\def\currstyle{####1}####1}\temp}%
\def\sectionstylelist{\tt,\sf,\bf,\rm,\it,\mdseries}%
\def\subsectionstylelist{\sl,\sc,\upshape}%
}
% Colors:
\def\usecolorpallete{%
\def\say{Current color: {\tt\detokenize\expandafter{\currstyle}}\par}%
\def\sayb{\def\currstyle{normal color}\normalcolor}%
\def\style{\def\temp####1{\def\currstyle{####1}\color{####1}}\temp}%
\def\sectionstylelist{orange,blue,red,red!50!black,ForestGreen}%
\def\subsectionstylelist{olive,magenta,cyan}%
}
\parindent0pt
\begin{multicols}{2}
\section{Title}
Normal style, default style.
\usecolorpallete
% Let's ignore font pallete in the current run:
%\usefontpallete
\newbodystyle[
body name = section,
style list command = \sectionstylelist,
repeated code = \style,
% Code to execute when \restorebodystyle is called:
exit code = \sayb
]
\newbodystyle[
body name = subsection,
style list command = \subsectionstylelist,
repeated code = \style,
exit code = \sayb
]
% A style may also be defined for 'paragraph'.
\section{Title}
\say aaa
\section{Title}
\say bbb
% Higher order cycles (eg, subsection) are independent of lower order
% cycles (eg, section):
\subsection{Subtitle}
\say ccc
\subsection{Subtitle}
\say ddd
\subsection{Subtitle}
\say eee
\subsection{Subtitle}
\say fff
\subsection{Subtitle}
\say ggg
% Restore subsection to default style:
\restorebodystyle{subsection}
\subsection{Subtitle}
\say hhh
\section{Title}
\say iii
\section{Title}
\say jjj
\section{Title}
\say kkk
\restorebodystyle{section}
\section{Title}
\say lll
\section{Title}
\say mmm
\end{multicols}
\end{document}

Just for fun, here is a cyclic loop that won't bomb out:
\documentclass{article}
\usepackage{xcolor}
\usepackage{catoptions}
\makeatletter
\newif\ifcyclicstop
% \cyclicdo[<max loop run>]<callback><listcmd>
\robust@def*\cyclicdo{\cpt@testopt\@cyclicdo{10000}}
\robust@def\@cyclicdo[#1]#2#3{%
\cyclicstopfalse
\def\cyclicnr{0}%
\def\@cyclica##1,##2{%
\edef\cyclicnr{\the\numexpr\cyclicnr+1}%
\ifnumcmpTF\cyclicnr>#1{%
\@latexerr{Max loop number #1 exceeded by \string\cyclicdo}\@ehd
}{%
#2{##1}%
\ifboolTF{cyclicstop}{%
\begingroup
\def\@cyclica####1\cyclicdo{\endgroup}%
\let\@cyclicb\@cyclica
}{}%
\expandafter\ifcseqTF\cpt@car##2x\car@nil\cyclicdo{%
\@cyclica##1,\cyclicdo
}{%
\@cyclicb##1,##2\@cyclicb
}%
}%
}%
\def\@cyclicb##1,##2\@cyclicb##3\cyclicdo{\@cyclica##2##3##1,\cyclicdo}%
\ifcsemptyTF{#3}{}{\expandafter\@cyclica#3,\cyclicdo}%
}
\makeatother
% Example document:
\begin{document}
\def\colorlist{yellow,magenta,cyan,orange,blue,green!30,red!50!black}
%\def\colorlist{yellow}
%\def\colorlist{}
\def\do#1{%
% Do only 10 cycles:
\ifnum\cyclicnr>10\relax\cyclicstoptrue\fi
{\color{#1}Current: \tt\detokenize{#1}}\endgraf
}
\cyclicdo\do\colorlist
\end{document}
