Half for fun, here is a solution using LaTeX3. It takes care of expanding your \SetA, \SetB and \MySets macros:
early enough to make the \foreach happy, and;
exactly once, so that in case your inner lists (\SetA and \SetB) contain things that should not be expanded, or should not be expanded too early, this solution could be usable as is (as opposed to solutions that use \edef\MySets{{\SetA},{\SetB}} or something similar, which fully expands \SetA and \SetB).
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{tikz}
\usepackage{xparse}
\usepackage[nopanel,screen]{pdfscreen}
\margins{1cm}{1cm}{1cm}{1cm}
\screensize{15.875cm}{20.32cm}
\ExplSyntaxOn
\clist_new:N \SetA
\clist_new:N \SetB
\clist_new:N \MySets
\clist_gset:Nn \SetA {example-image-a/caption~A1, example-image-a/caption~A2}
\clist_gset:Nn \SetB {example-image-b/caption~B1, example-image-b/caption~B2}
\clist_gset:Nn \MySets {\SetA, \SetB}
\cs_new_protected:Npn \ross_iterate_on_sets:NN #1#2
{
\clist_map_variable:NNn #2 #1
}
\NewDocumentCommand \RossIterateOnSets { m m }
{
\ross_iterate_on_sets:NN #1 #2
}
\cs_new_protected:Npn \ross_iterate_on_pics:nn #1#2
{
\foreach #1 ~in~ {#2}
}
\cs_generate_variant:Nn \ross_iterate_on_pics:nn { nV }
\NewDocumentCommand \RossIterateOnPics { m m }
{
% First expansion of #2 (e.g. \Set -> \SetA or \SetB)
\exp_args:Nno
% Second expansion: use the *value* of \SetA or \SetB for the second
% argument of \ross_iterate_on_pics:nn
\ross_iterate_on_pics:nV {#1} {#2}
}
\ExplSyntaxOff
\begin{document}
\RossIterateOnSets{\Set}{\MySets} {%
\RossIterateOnPics{\myphoto/\mycaption}{\Set} {%
\centering
\begin{tikzpicture}
\node (a) at (0,0) {%
\includegraphics[width=0.9\linewidth,height=0.9\textheight]{\myphoto}};
\node[below=3mm] (b) at (a.south) {\mycaption};
\end{tikzpicture}
\clearpage
}%
}
\end{document}
If one of the elements of a comma-list should contain a comma, just wrap the whole element in braces.
In order to see for yourself that things are expanded as advertised before being fed to \foreach (i.e., each of \SetA, \SetB and \MySets is expanded exactly once before arriving in the hands of \foreach), please consider this slightly modified version, where we print to the terminal and log file precisely what the inner loop does:
\documentclass{article}
\usepackage{xparse}
\newcommand*{\dontExpandMe}{If this gets printed, it is GAME OVER.}
\ExplSyntaxOn
\clist_new:N \SetA
\clist_new:N \SetB
\clist_new:N \MySets
\clist_gset:Nn \SetA {example-image-a/caption~\dontExpandMe A1,
example-image-a/caption~A2}
\clist_gset:Nn \SetB {example-image-b/caption~B1,
example-image-b/caption~\dontExpandMe B2}
\clist_gset:Nn \MySets {\SetA, \SetB}
\cs_new_protected:Npn \ross_iterate_on_sets:NN #1#2
{
\clist_map_variable:NNn #2 #1
}
\NewDocumentCommand \RossIterateOnSets { m m }
{
\ross_iterate_on_sets:NN #1 #2
}
\cs_new_protected:Npn \ross_iterate_on_pics:nn #1#2
{
\typeout { \string\foreach \unexpanded {#1} ~in~ \unexpanded {{#2}} }
}
\cs_generate_variant:Nn \ross_iterate_on_pics:nn { nV }
\NewDocumentCommand \RossIterateOnPics { m m }
{
% First expansion of #2 (e.g. \Set -> \SetA or \SetB)
\exp_args:Nno
% Second expansion: use the *value* of \SetA or \SetB for the second
% argument of \ross_iterate_on_pics:nn
\ross_iterate_on_pics:nV {#1} {#2}
}
\ExplSyntaxOff
\begin{document}
\RossIterateOnSets{\Set}{\MySets} {%
\RossIterateOnPics{\myphoto/\mycaption}{\Set}
}
\end{document}
Here is the output (on the terminal and in the log file) of the two \typeout commands of this example:
\foreach\myphoto /\mycaption in {example-image-a/caption \dontExpandMe A1,example-image-a/caption A2}
\foreach\myphoto /\mycaption in {example-image-b/caption B1,example-image-b/caption \dontExpandMe B2}
As you can see, the \dontExpandMe macro is not expanded. In the full example, this means it would not be expanded before the \foreach is executed.
Note: \mycaption is followed by two spaces in this output:
the first one is from \typeout printing a control word (i.e., a control sequence composed of letters only);
the second one is because we put an explicit space token (~ in expl3 syntax) before the word in.
Similarly, \dontExpandMe is followed by exactly one space in the output because it is a control word printed by \typeout.
Note 2: using \unexpanded is necessary to see the tokens as is. This is because \typeout expands everything inside its argument (like \message, but \typeout is also \protect-aware as explained in this answer).
clistvariables is done in my solution (one of its strong points). – frougon May 03 '19 at 15:56